Primary navigation

Plugin submission errors

Find and fix validation errors for plugins submitted to the public directory

Plugins submitted to the public directory are held to a higher standard than plugins installed in a workspace. Directory submissions must pass the shared package checks and the additional checks for listing fields, review materials, MCP tools, skills, assets, and images. This reference also covers shared package checks, such as app references, that can appear outside the submission portal.

Use the error code returned during submission to find the matching requirement. Errors block submission. Warnings don’t block submission, but you should review them before continuing.

Non-empty values can’t contain only whitespace. Supported text excludes control characters, Unicode line or paragraph separators, and unsupported invisible formatting characters. HTTPS URLs must include a host and contain no embedded credentials or unsupported characters.

Final directory submission

A package can pass upload validation and still fail final directory submission. Final submission uses stricter listing limits and checks MCP configuration, skill scans, test cases, and policy attestations.

FieldFinal submission rule
Package nameRequired; at most 64 characters. Start with an ASCII letter or digit and use only ASCII letters, digits, _, and -.
VersionRequired; use a semantic version of at most 64 characters.
Display nameRequired; one line; at most 30 characters.
Short descriptionRequired; one line; at most 30 characters.
Long descriptionRequired; at most 4,000 characters. Line breaks are allowed.
Developer nameRequired; one line; at most 80 characters.
CategoryRequired; choose a supported category listed in the Listing and interface errors section.
CapabilitiesAt most 20. Each capability must be non-empty, one line, and at most 120 characters.
Starter promptsAt most 3. Each prompt must be non-empty, unique after Unicode and whitespace normalization, one line, at most 128 characters, and contain no app @mention.
URLsRequired for MCP-backed submissions; optional for skills-only submissions. Website, support, privacy policy, and terms URLs must use HTTPS and be at most 1,024 characters.
Brand colorsOptional six-digit hex colors. The light color must have at least 2:1 contrast against white, and the dark color must have at least 2:1 contrast against #212121.

Every plugin submission also requires:

  • Passing safety and security scans for every bundled skill. Scans can take up to 2 hours.
  • A verified developer or business identity and all required policy attestations.

For an MCP-backed plugin, final submission also requires:

  • Website, support, privacy policy, and terms URLs that meet the rules above.
  • A demo-recording URL that shows the main use cases and tools across supported platforms.
  • Exactly five positive test cases, three negative test cases, and release notes.
  • A production HTTPS MCP server URL, a completed domain-verification challenge, and a successful, current tool scan.
  • Explicit readOnlyHint, openWorldHint, and destructiveHint values and a justification for each value on every MCP tool.
  • Reviewer-ready demo credentials when the server uses OAuth.
  • Screenshots only when the MCP server provides custom UI. If you add screenshots, provide one PNG or JPEG image for every starter prompt. Each screenshot must be exactly 706 pixels wide and 400–860 pixels tall.

Final metadata errors

In these error names, subtitle means short description and description means long description.

NameRequirement
submission_display_name_requiredDisplay name is required, non-empty, and single-line.
submission_display_name_too_longDisplay name must be 30 characters or fewer.
submission_display_name_character_unsupportedDisplay name must use supported text and fit on one line.
submission_subtitle_requiredShort description is required, non-empty, and single-line.
submission_subtitle_too_longShort description must be 30 characters or fewer.
submission_subtitle_character_unsupportedShort description must use supported text and fit on one line.
submission_description_requiredLong description is required and must be non-empty. Line breaks are allowed.
submission_description_too_longLong description must be 4,000 characters or fewer.
submission_description_character_unsupportedLong description must use supported text. Line breaks are allowed.
submission_developer_name_requiredDeveloper name is required, non-empty, and single-line.
submission_developer_name_too_longDeveloper name must be 80 characters or fewer.
submission_developer_name_character_unsupportedDeveloper name must use supported text and fit on one line.
plugin_capability_invalidEach capability must be non-empty, use supported text, fit on one line, and be 120 characters or fewer.
plugin_default_prompt_mentionStarter prompts must not contain app @mentions.
plugin_default_prompt_duplicateStarter prompts must be unique after Unicode and whitespace normalization.

MCP and review errors

These errors apply to MCP-backed submissions.

NameRequirement
annotations_requiredEvery MCP tool must set readOnlyHint, openWorldHint, and destructiveHint accurately.
justification_requiredEvery MCP tool annotation must include a justification for its read-only, open-world, or destructive behavior.
scan_requiredMCP tools must have a successful, current scan of the production MCP server.
domain_verification_requiredThe exact verification token must be hosted at the generated /.well-known/openai-apps-challenge URL on the MCP host or an allowed parent host, and Verify Domain must pass.
frame_domain_explanation_requiredEvery external frame domain reported by the MCP tool scan must have an explanation of why the UI needs it and what content it provides.
screenshots_not_allowedScreenshots are allowed only when the current MCP tool scan reports a UI output template.

Archive errors

Skills-only ZIP upload errors and warnings

Skills only uploads accept a plugin manifest and bundled skills. A changed package name blocks an update; the other findings require confirmation.

NameRequirement
plugin_name_mismatchThe package name in an update must match the existing plugin name.
plugin_version_unchangedA new release must use a different manifest version; reusing the published version requires confirmation.
mcp_configuration_excludedSkills-only ZIP uploads must not include mcpServers or .mcp.json; MCP-backed plugins must use With MCP.
app_configuration_excludedSkills-only ZIP uploads must not include apps or .app.json; plugins with app content must use With MCP.
screenshot_configuration_excludedSkills-only ZIP uploads must not include interface.screenshots; screenshots require With MCP and custom UI.
claude_format_normalized.claude-plugin/plugin.json is converted to .codex-plugin/plugin.json, with missing interface defaults and normalized text fields added by the portal.
manifest_normalizedThe portal saves the normalized manifest as .codex-plugin/plugin.json; changed fields require confirmation.
developer_name_defaultedauthor.name and interface.developerName must match, or the selected verified identity is used for both after confirmation.

ZIP structure and limit errors

NameRequirement
archive_emptyArchive must not be empty.
archive_too_largeCompressed ZIP must be 100 MB or less.
archive_format_not_zipArchive must be a valid, uncorrupted ZIP file.
archive_member_path_emptyArchive entry path must not be empty.
archive_member_path_has_outer_whitespaceArchive entry path must not begin or end with whitespace.
archive_member_path_has_backslashArchive entry path must use /, not backslashes.
archive_member_path_absoluteArchive entry path must be relative to the archive root.
archive_member_path_has_empty_segmentArchive entry path must not contain empty segments.
archive_member_path_has_parent_segmentArchive entry path must not contain .. segments.
archive_member_path_too_deepArchive entry path must contain at most 20 segments, including the filename.
archive_member_path_too_longArchive entry path must be within the supported path-length limit.
archive_member_path_normalization_collisionArchive entry paths must remain unique after case and Unicode normalization.
archive_member_type_unsupportedArchive entries must be regular files or directories.
archive_member_too_largeArchive entry must not exceed 100 MiB.
archive_member_path_duplicateArchive entry path must be unique.
archive_member_path_type_conflictA file path cannot also be a directory or contain another archive entry.
archive_too_many_entriesArchive must not contain more than 5,000 entries.
archive_uncompressed_too_largeExtracted archive must not exceed 512 MiB.
archive_member_unreadableEvery archive entry must be readable, must not be encrypted, and must use supported compression.

Plugin root errors

NameRequirement
plugin_root_missingThe selected path must exist and be a directory containing a plugin.
archive_plugin_files_missingA skills-only ZIP must contain a supported plugin manifest and at least one valid skill at skills/<skill>/SKILL.md.
plugin_root_ambiguousZIP must contain exactly one plugin root, either at the archive root or in one top-level directory.
plugin_root_has_siblingsA ZIP with a top-level plugin directory must not contain sibling files.

Plugin manifest errors

NameRequirement
plugin_manifest_missingZIP must contain .codex-plugin/plugin.json, .agent-plugin/plugin.json, or .claude-plugin/plugin.json at the root or in its single top-level directory.
plugin_manifest_not_filePlugin manifest must be a regular JSON file.
plugin_manifest_unreadablePlugin manifest must be readable UTF-8 text.
plugin_manifest_json_malformedPlugin manifest must contain valid JSON; malformed syntax is reported with a line number.
plugin_manifest_root_not_objectPlugin manifest must contain a JSON object at the top level.
codex_manifest_parent_not_directory.codex-plugin must be a directory.
codex_manifest_path_not_file.codex-plugin/plugin.json must be a regular JSON file.
plugin_id_wrong_typeid must be a string when provided.
plugin_id_emptyid must be non-empty when provided.
plugin_name_missingname is required.
plugin_name_wrong_typename must be a string.
plugin_name_emptyname must be non-empty.
plugin_name_too_longname must be 64 characters or fewer.
plugin_name_formatname must start with an ASCII letter or digit and contain only ASCII letters, digits, _, or -.
plugin_version_missingversion is required.
plugin_version_wrong_typeversion must be a string.
plugin_version_emptyversion must be a non-empty semantic-version string, such as 1.0.0.
plugin_version_not_semverversion must use semantic versioning, such as 1.0.0.
plugin_version_too_longversion must be 64 characters or fewer.
plugin_description_missingdescription is required.
plugin_description_wrong_typedescription must be a string.
plugin_description_emptydescription must be non-empty.
plugin_description_too_longdescription must be 1,024 characters or fewer.
plugin_description_character_unsupporteddescription must use supported text. Line breaks are allowed.
plugin_developer_missingauthor.name is required. interface.developerName is also required and is reported separately.
plugin_author_wrong_typeauthor must be an object.
plugin_author_name_wrong_typeauthor.name must be a string.
plugin_author_name_emptyauthor.name must be non-empty.
plugin_author_name_too_longauthor.name must be 120 characters or fewer.
plugin_author_name_character_unsupportedauthor.name must use supported text.
plugin_author_email_wrong_typeauthor.email must be a string when provided.
plugin_author_email_emptyauthor.email must be non-empty when provided.
plugin_author_email_too_longauthor.email must be 320 characters or fewer.
plugin_author_email_character_unsupportedauthor.email must use supported text.
plugin_author_url_wrong_typeauthor.url must be a string when provided.
plugin_author_url_emptyauthor.url must be non-empty when provided.
plugin_author_url_not_httpsauthor.url must be an HTTPS URL.
plugin_author_url_has_credentialsauthor.url must not contain credentials.
plugin_author_url_too_longauthor.url must be 2,048 characters or fewer.
plugin_author_url_character_unsupportedauthor.url must use supported text.

Listing and interface errors

The plugin manifest’s interface object defines the public listing shown to users. It lives in .codex-plugin/plugin.json and uses fields such as displayName and shortDescription:

{
  "interface": {
    "displayName": "Example Plugin",
    "shortDescription": "Summarize documents",
    "longDescription": "Summarize and organize documents.",
    "developerName": "Example",
    "category": "Productivity",
    "capabilities": ["Summarize documents"]
  }
}

The four listing URLs (website, privacy policy, terms, and support) are optional for skills-only plugins and required for MCP-backed plugins. Their length limit is 2,048 characters for package validation and 1,024 characters for final directory submission.

NameRequirement
plugin_interface_wrong_typeThe plugin manifest’s interface field must be a JSON object.
plugin_display_name_wrong_typeinterface.displayName must be a string.
plugin_display_name_emptyinterface.displayName is required and must be non-empty.
plugin_display_name_too_longinterface.displayName must be 80 characters or fewer for package validation and 30 characters or fewer for final directory submission.
plugin_display_name_character_unsupportedinterface.displayName must use supported text.
plugin_short_description_missinginterface.shortDescription is required, must fit on one line, and must be 240 characters or fewer for package validation and 30 characters or fewer for final directory submission.
plugin_short_description_wrong_typeinterface.shortDescription must be a string.
plugin_short_description_emptyinterface.shortDescription must be non-empty.
plugin_short_description_too_longinterface.shortDescription must be 240 characters or fewer for package validation and 30 characters or fewer for final directory submission.
plugin_short_description_character_unsupportedinterface.shortDescription must use supported text.
plugin_long_description_wrong_typeinterface.longDescription must be a string.
plugin_long_description_emptyinterface.longDescription is required and must be non-empty.
plugin_long_description_too_longinterface.longDescription must be 4,000 characters or fewer.
plugin_long_description_character_unsupportedinterface.longDescription must use supported text. Line breaks are allowed.
plugin_developer_name_wrong_typeinterface.developerName must be a string.
plugin_developer_name_emptyinterface.developerName is required and must be non-empty.
plugin_developer_name_too_longinterface.developerName must be 120 characters or fewer for package validation and 80 characters or fewer for final directory submission.
plugin_developer_name_character_unsupportedinterface.developerName must use supported text.
plugin_category_wrong_typeinterface.category must be a string.
plugin_category_emptyinterface.category must be non-empty when provided; omit it to use Other.
plugin_category_unknowninterface.category must be Productivity, Creativity, Developer Tools, Business & Operations, Data & Analytics, Communication, Education & Research, Security, Finance, Healthcare, Travel, Entertainment, or Other.
plugin_category_character_unsupportedinterface.category must use supported text.
plugin_capabilities_wrong_typeinterface.capabilities must be a list of strings.
plugin_capabilities_too_manyinterface.capabilities must contain 20 entries or fewer.
plugin_capability_wrong_typeEach interface.capabilities entry must be a string.
plugin_capability_emptyEach interface.capabilities entry must be non-empty when provided.
plugin_capability_too_longEach interface.capabilities entry must be 120 characters or fewer.
plugin_capability_character_unsupportedEach interface.capabilities entry must use supported text.
plugin_website_url_wrong_typeinterface.websiteURL must be a string when provided.
plugin_website_url_emptyinterface.websiteURL must be non-empty when provided.
plugin_website_url_formatinterface.websiteURL must be an HTTPS URL.
plugin_website_url_too_longinterface.websiteURL must meet the listing URL length limits.
plugin_privacy_policy_url_wrong_typeinterface.privacyPolicyURL must be a string when provided.
plugin_privacy_policy_url_emptyinterface.privacyPolicyURL must be non-empty when provided.
plugin_privacy_policy_url_formatinterface.privacyPolicyURL must be an HTTPS URL.
plugin_privacy_policy_url_too_longinterface.privacyPolicyURL must meet the listing URL length limits.
plugin_terms_of_service_url_wrong_typeinterface.termsOfServiceURL must be a string when provided.
plugin_terms_of_service_url_emptyinterface.termsOfServiceURL must be non-empty when provided.
plugin_terms_of_service_url_formatinterface.termsOfServiceURL must be an HTTPS URL.
plugin_terms_of_service_url_too_longinterface.termsOfServiceURL must meet the listing URL length limits.
plugin_support_url_wrong_typeinterface.supportURL must be a string when provided.
plugin_support_url_emptyinterface.supportURL must be non-empty when provided.
plugin_support_url_formatinterface.supportURL must be an HTTPS URL.
plugin_support_url_too_longinterface.supportURL must meet the listing URL length limits.
plugin_homepage_wrong_typehomepage must be a string when provided.
plugin_homepage_emptyhomepage must be non-empty when provided.
plugin_homepage_formathomepage must be an HTTPS URL.
plugin_homepage_too_longhomepage must be 2,048 characters or fewer.
plugin_brand_color_wrong_typeinterface.brandColor must be a string when provided.
plugin_brand_color_emptyinterface.brandColor must be non-empty when provided.
plugin_brand_color_formatinterface.brandColor must be a six-digit hex color, such as #1ABCFE.
plugin_brand_color_dark_wrong_typeinterface.brandColorDark must be a string when provided.
plugin_brand_color_dark_emptyinterface.brandColorDark must be non-empty when provided.
plugin_brand_color_dark_formatinterface.brandColorDark must be a six-digit hex color, such as #1ABCFE.
plugin_brand_color_contrastinterface.brandColor must have at least 2:1 contrast against white.
plugin_brand_color_dark_contrastinterface.brandColorDark must have at least 2:1 contrast against #212121.
plugin_default_prompt_wrong_typeinterface.defaultPrompt must be a string or list of strings.
plugin_default_prompt_too_manyinterface.defaultPrompt must contain at most three prompts.
plugin_default_prompt_entry_wrong_typeEach interface.defaultPrompt entry must be a string.
plugin_default_prompt_emptyEach interface.defaultPrompt entry must be non-empty when provided.
plugin_default_prompt_too_longEach interface.defaultPrompt entry must be 512 characters or fewer for package validation and 128 characters or fewer for final directory submission.
plugin_default_prompt_character_unsupportedEach interface.defaultPrompt entry must use supported text and fit on one line.

Plugin content errors

NameRequirement
plugin_skills_path_wrong_typeskills must be a string path for the root skills/ directory.
plugin_skills_path_emptyskills must be a non-empty path to the root skills/ directory when provided.
plugin_skills_path_unsupportedskills must resolve to the root skills/ directory.
plugin_skills_directory_missingA declared root skills/ directory must exist.
plugin_skills_path_not_directoryRoot skills/ must be a directory when declared.
plugin_apps_path_wrong_typeapps must be a string path for the root .app.json.
plugin_apps_path_emptyapps must be a non-empty path to the root .app.json when provided.
plugin_apps_path_unsupportedapps must resolve to the root .app.json.
plugin_apps_file_missingA declared root .app.json file must exist.
plugin_apps_path_not_fileRoot .app.json must be a regular file when declared.
plugin_runtime_surface_missingA skills-only ZIP must contain at least one valid skill at skills/<skill>/SKILL.md; app and MCP references don’t satisfy this requirement.

Skill errors

NameRequirement
skill_manifest_missingSkill must contain a SKILL.md file.
skill_bundle_too_largeEach compressed skill bundle must be within the MiB limit reported in the error.
skill_directory_hiddenSkill directory names must not begin with ..
skill_manifest_nestedEach skill directory must be an immediate child of skills/.
skill_manifest_not_regular_fileSKILL.md must be a regular file.
skill_manifest_unreadableSKILL.md must be readable.
skill_manifest_invalid_utf8SKILL.md must contain valid UTF-8.
skill_frontmatter_missingSKILL.md must start with YAML front matter between --- lines.
skill_frontmatter_unclosedSKILL.md YAML front matter must end with ---.
skill_frontmatter_yaml_malformedSKILL.md front matter must contain valid YAML.
skill_frontmatter_wrong_typeSKILL.md front matter must contain a YAML mapping.
skill_name_missingname is required and must not be empty.
skill_name_wrong_typename must be a string.
skill_name_emptyname must be non-empty.
skill_name_character_unsupportedSkill front matter name must use supported text.
skill_description_missingdescription is required and must not be empty.
skill_description_wrong_typedescription must be a string.
skill_description_emptydescription must be non-empty.
skill_description_too_longdescription must be 1,024 characters or fewer.
skill_description_character_unsupportedSkill front matter description must use supported text.
skill_body_emptySkill instructions must not be empty.
skill_identity_too_longThe combined plugin and skill name (plugin-name:skill-name) must be 64 characters or fewer.
skill_identity_duplicateEach skill name must be unique within the plugin.

Skill agent metadata errors

A bundled skill can define its own interface in skills/<skill>/agents/openai.yaml. This controls how the skill appears to users and is separate from the plugin manifest’s interface. Skill interface fields use snake_case:

interface:
  display_name: "Summarize documents"
  short_description: "Summarize a document"
  icon_small: "./assets/icon.png"
  default_prompt: "Summarize the selected document."
NameRequirement
skill_agent_not_regular_fileagents/openai.yaml must be a regular file.
skill_agent_unreadableagents/openai.yaml must be readable.
skill_agent_invalid_utf8agents/openai.yaml must contain valid UTF-8.
skill_agent_yaml_malformedagents/openai.yaml must contain valid YAML.
skill_agent_top_level_wrong_typeagents/openai.yaml must contain a YAML mapping at the top level.
skill_agent_interface_missinginterface is required in agents/openai.yaml when that file is included.
skill_agent_interface_wrong_typeinterface in agents/openai.yaml must be a YAML mapping.
skill_agent_display_name_missinginterface.display_name is required and must not be empty.
skill_agent_display_name_wrong_typeinterface.display_name must be a string.
skill_agent_display_name_emptyinterface.display_name must not be empty.
skill_agent_short_description_missinginterface.short_description is required and must not be empty.
skill_agent_short_description_wrong_typeinterface.short_description must be a string.
skill_agent_short_description_emptyinterface.short_description must not be empty.
skill_agent_icon_small_wrong_typeinterface.icon_small must be a non-empty relative file path when provided.
skill_agent_icon_small_emptyinterface.icon_small must be a non-empty relative file path when provided, such as assets/icon.png.
skill_agent_icon_large_wrong_typeinterface.icon_large must be a non-empty relative file path when provided.
skill_agent_icon_large_emptyinterface.icon_large must be a non-empty relative file path when provided, such as assets/icon.png.
skill_agent_brand_color_wrong_typeinterface.brand_color must be a string when provided.
skill_agent_brand_color_emptyinterface.brand_color must be a non-empty six-digit hex color when provided, such as #1ABCFE.
skill_agent_brand_color_formatinterface.brand_color must be a six-digit hex color, such as #1ABCFE.
skill_agent_default_prompt_wrong_typeinterface.default_prompt must be a string when provided.
skill_agent_default_prompt_emptyinterface.default_prompt must be non-empty when provided.
skill_agent_policy_wrong_typepolicy must be a YAML mapping when provided.
skill_agent_allow_implicit_invocation_wrong_typepolicy may contain only products and allow_implicit_invocation. products must contain CHAT, CODEX, or both, and allow_implicit_invocation must be true or false.
skill_agent_dependencies_wrong_typedependencies must be a YAML mapping; only tools is supported.
skill_agent_dependency_unsupportedOnly dependencies.tools is supported in agents/openai.yaml.

Asset path errors

NameRequirement
declared_asset_path_wrong_typeThe named asset field must be a file path string.
declared_asset_path_emptyThe named asset field must not be empty.
declared_asset_path_has_outer_whitespaceThe named asset field must not begin or end with whitespace.
declared_asset_path_has_control_characterThe named asset field must not contain characters U+0000–U+001F or U+007F.
branding_asset_path_missing_root_prefixThe named asset field must start with ./.
declared_asset_path_unsafeThe named asset field must be a relative path inside the plugin and must not contain an absolute path, drive prefix, or .. traversal segment.
declared_asset_path_outside_packageThe named asset field must reference a file inside the plugin.
declared_asset_file_missingThe named asset field references a file that does not exist.
declared_asset_not_regular_fileThe named asset field must reference a file, not a directory or special file.

Image errors

Directory branding images must use a supported file type and meet the size and dimension limits below. These rules apply to packaged branding assets; starter-prompt screenshots use the separate portal limits listed above.

NameRequirement
plugin_logo_path_missinginterface.logo is required and must reference a square image.
plugin_composer_icon_path_missinginterface.composerIcon is required and must reference a square image.
image_file_unreadableImage file must be readable.
image_file_too_largeImage must not exceed 5 MiB.
image_file_format_unsupportedImage filename must end in .png, .jpg, .jpeg, .webp, or .svg.
raster_image_decode_failedRaster image must be a PNG, JPEG, or WebP file that can be decoded safely.
raster_image_extension_content_mismatchImage filename extension must match the detected image format.
raster_image_not_squareImage must be square.
raster_image_dimensions_too_smallImage dimensions must be at least 48×48 pixels.
raster_image_dimensions_too_largeImage dimensions must not exceed 4,096×4,096 pixels.
svg_xml_malformedSVG must contain valid UTF-8 XML.
svg_root_element_invalidSVG root element must be <svg>.
svg_dimensions_missingSVG must define a numeric viewBox or numeric width and height.
svg_dimensions_not_numericSVG dimensions must be numeric and omit units and percentages.
svg_dimensions_not_positiveSVG width and height must be positive finite numbers.
svg_dimensions_not_squareSVG dimensions must be square.
svg_dimensions_too_smallSVG dimensions must be at least 48×48 pixels.

App reference errors

The shared package checks validate .app.json when a plugin references apps. The submission portal doesn’t publish references to existing ChatGPT apps: a Skills only upload removes .app.json, and an MCP-backed submission must use With MCP and submit the MCP server directly.

For local or workspace packages, the top-level apps object maps each app alias to an app entry.

NameRequirement
app_manifest_unreadable.app.json must be readable UTF-8 text.
app_manifest_json_malformed.app.json contains malformed JSON near the reported line.
app_manifest_wrong_type.app.json must contain a JSON object at the top level.
app_entries_missingapps is required.
app_entries_wrong_typeapps must be an object.
app_entry_wrong_typeEach app entry must be an object.
app_id_missingEach app entry’s id is required.
app_id_wrong_typeEach app entry’s id must be a string.
app_id_formatEach app entry’s id must begin with asdk_app_, connector_, or templated_apps_, followed by a letter or digit and then only letters, digits, _, or -.
app_entry_optional_wrong_typeEach app entry’s optional value must be true or false when provided.
app_entry_required_wrong_typeEach app entry’s required value must be true or false when provided.
app_not_eligibleFor a local or workspace package, each referenced app must be a released public Codex app, available connector, or released app template. Directory submissions must use With MCP and submit the MCP server directly.

Package warnings

These warnings identify package content that validation ignores or normalizes. They don’t block submission. Review them to confirm the submitted plugin contains the expected files and settings.

NameRequirement
duplicate_app_referenceEach app ID in .app.json must be referenced once; duplicate references are treated as one app.
undeclared_app_manifest_ignoredA root .app.json is imported only when the plugin-manifest apps field is set to ./.app.json.
undeclared_mcp_manifest_ignoredA root .mcp.json is imported only when the plugin-manifest mcpServers field is set to ./.mcp.json.
skill_file_ignoredFiles directly under skills/ aren’t imported as skills; each skill must be in a directory containing SKILL.md.
skill_symlink_ignoredSymbolic links directly under skills/ aren’t imported as skills; each skill must be a real directory containing SKILL.md.
skill_frontmatter_adjustedSkill name and description are normalized during import by trimming outer whitespace and collapsing internal whitespace.
skill_metadata_ignoredSkill interface settings must use the interface mapping in agents/openai.yaml; metadata in SKILL.md doesn’t configure the interface.

Next steps

After resolving all validation errors, return to Submit plugins to complete the submission.