{"record":{"id":"1cb04b4cb9dfd53e","repo":"quarkusio/quarkus","slug":"quarkus-extension-yaml-is-empty-or-contains-no-obj","errorCode":null,"errorMessage":"quarkus-extension.yaml is empty or contains no object","messagePattern":"quarkus-extension\\.yaml is empty or contains no object","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/utils/SkillComposer.java","lineNumber":52,"sourceCode":"    /**\n     * Returns the output path for a composed skill file inside the deployment JAR,\n     * following the Agent Skills directory convention.\n     *\n     * @param skillName the skill identifier (e.g. {@code quarkus-arc})\n     */\n    public static String outputSkillPath(String skillName) {\n        return \"META-INF/skills/\" + skillName + \"/SKILL.md\";\n    }\n\n    /**\n     * Parses a {@code quarkus-extension.yaml} from the given input stream.\n     *\n     * @throws IOException if the stream cannot be read, the YAML is malformed, or the file is empty\n     */\n    public static ObjectNode parseExtensionMetadata(InputStream is) throws IOException {\n        final ObjectNode result = YAML_MAPPER.readValue(is, ObjectNode.class);\n        if (result == null) {\n            throw new IOException(\"quarkus-extension.yaml is empty or contains no object\");\n        }\n        return result;\n    }\n\n    /**\n     * Composes a skill document from extension metadata and raw skill content,\n     * producing a {@code SKILL.md} file with YAML frontmatter per the\n     * <a href=\"https://agentskills.io/specification\">Agent Skills specification</a>.\n     *\n     * @param extMeta the parsed {@code quarkus-extension.yaml} as an {@link ObjectNode}\n     * @param rawContent the raw skill file content authored by the extension developer\n     * @param skillName the skill identifier used in the frontmatter {@code name} field\n     *        (e.g. {@code quarkus-arc}, derived from the runtime artifact name)\n     * @param license the SPDX license identifier (e.g. {@code Apache-2.0}), may be {@code null}\n     */\n    public static String compose(ObjectNode extMeta, String rawContent, String skillName, String license) {\n        Objects.requireNonNull(extMeta, \"extMeta must not be null\");\n        Objects.requireNonNull(rawContent, \"rawContent must not be null\");","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/utils/SkillComposer.java#L34-L70","documentation":"SkillComposer.parseExtensionMetadata(InputStream) deserializes quarkus-extension.yaml into a Jackson ObjectNode. If YAML_MAPPER.readValue returns null — meaning the stream was empty or contained no YAML object — it throws IOException(\"quarkus-extension.yaml is empty or contains no object\") because downstream skill composition requires extension metadata.","triggerScenarios":"Calling parseExtensionMetadata with an InputStream whose content is empty, whitespace-only, or parses to no object (null) — e.g. reading a quarkus-extension.yaml that was truncated to zero bytes or contains only comments.","commonSituations":"A built/installed extension JAR contains an empty quarkus-extension.yaml because the extension processor failed to generate it; a file was truncated during copy/deployment; a hand-edited metadata file had its content wiped; reading from a stream already consumed or closed upstream yielding empty input.","solutions":["Verify the quarkus-extension.yaml exists and has non-empty object content in the source JAR/directory.","Rebuild the extension (mvn install) so the extension descriptor is regenerated.","Check that the InputStream is positioned at the start and actually delivers bytes (not already consumed).","Validate the YAML parses to an object (e.g. with a quick YAML parser) before composing the skill."],"exampleFix":"// before: empty/invalid descriptor\n// quarkus-extension.yaml: (0 bytes)\n// after: minimal valid descriptor\nartifact: \"${project.groupId}:${project.artifactId}::jar:${project.version}\"\nname: \"My Extension\"\nmetadata:\n  unlisted: true","handlingStrategy":"validation","validationCode":"byte[] bytes = is.readAllBytes();\nif (bytes.length == 0) {\n    throw new IOException(\"quarkus-extension.yaml is empty\");\n}\nObjectNode node = SkillComposer.parseExtensionMetadata(new ByteArrayInputStream(bytes));","typeGuard":"static boolean hasExtensionMetadata(InputStream is) throws IOException {\n    try (is) {\n        return is.read() != -1; // non-empty stream\n    }\n}","tryCatchPattern":"try {\n    ObjectNode meta = SkillComposer.parseExtensionMetadata(is);\n} catch (IOException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"empty\")) {\n        log.error(\"Descriptor empty; rebuild the extension JAR to regenerate quarkus-extension.yaml\");\n    }\n}","preventionTips":["Verify quarkus-extension.yaml is non-empty in the extension JAR before composing skills.","Rebuild the extension if its processor failed to emit the descriptor.","Reset the InputStream to the start before parsing (avoid already-consumed streams).","Validate YAML files in CI so empty/comment-only descriptors are caught early."],"tags":["yaml","validation","extension-metadata"],"backgroundTag":"empty-descriptor","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}