{"record":{"id":"8e6d4050f0245c6e","repo":"conductor-oss/conductor","slug":"skill-manifest-name-manifestname-does-not-matc","errorCode":null,"errorMessage":"Skill manifest name '{manifestName}' does not match package SKILL.md name '{name}'","messagePattern":"Skill manifest name '(.+?)' does not match package SKILL\\.md name '(.+?)'","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"agentspan/src/main/java/org/conductoross/conductor/ai/agentspan/runtime/service/SkillRegistryService.java","lineNumber":154,"sourceCode":"        }\n    }\n\n    public synchronized SkillDetail register(String manifestJson, MultipartFile packageFile) {\n        requireSkillStorage();\n        if (packageFile == null || packageFile.isEmpty()) {\n            throw new IllegalArgumentException(\"Skill package is required\");\n        }\n\n        Map<String, Object> manifest = parseManifest(manifestJson);\n        byte[] bytes = readPackage(packageFile);\n        String checksum = sha256Hex(bytes);\n\n        ParsedSkillPackage parsed = parseSkillPackage(bytes, manifest);\n        String name = parsed.name();\n        Map<String, Object> rawConfig = parsed.rawConfig();\n        String manifestName = stringValue(manifest.get(\"name\"));\n        if (manifestName != null && !manifestName.isBlank() && !manifestName.equals(name)) {\n            throw new IllegalArgumentException(\n                    \"Skill manifest name '\"\n                            + manifestName\n                            + \"' does not match package SKILL.md name '\"\n                            + name\n                            + \"'\");\n        }\n\n        String version = stringValue(manifest.get(\"version\"));\n        if (version == null || version.isBlank()) {\n            version = checksum.substring(0, 12);\n        }\n        validateVersion(version);\n        pinRegisteredCrossSkillRefs(rawConfig);\n\n        long now = Instant.now().toEpochMilli();\n\n        Optional<SkillDetail> existingOpt = metadataDao.find(name, version);\n        if (existingOpt.isPresent()) {","sourceCodeStart":136,"sourceCodeEnd":172,"githubUrl":"https://github.com/conductor-oss/conductor/blob/cf7c3e4a8adfb158be778ab1ec525323c363cd3a/agentspan/src/main/java/org/conductoross/conductor/ai/agentspan/runtime/service/SkillRegistryService.java#L136-L172","documentation":"Thrown by register() when the 'name' field in the JSON manifest part does not match the 'name' parsed from the SKILL.md YAML frontmatter inside the uploaded zip package. The manifest is the @RequestPart(\"manifest\") and the package SKILL.md is the source of truth; the two must agree. This guards against accidental name drift between the registration metadata and the actual skill payload.","triggerScenarios":"POST /api/skills/register with a manifest body containing \"name\":\"my-skill\" while the zip's SKILL.md frontmatter declares name: my-skill-v2. Also fires when the manifest name has trailing whitespace or a typo relative to SKILL.md. Triggered only when manifestName is non-blank AND differs from parsed.name().","commonSituations":"Renaming a skill by editing only the manifest JSON without rebuilding the zip; CI pipelines that template the manifest separately from the SKILL.md; copy-pasting a manifest between skills and forgetting to update one of the two name fields.","solutions":["Make the manifest 'name' exactly equal to the SKILL.md frontmatter 'name' (case-sensitive, no surrounding whitespace).","Omit the 'name' field from the manifest entirely — if manifestName is null/blank the check is skipped and SKILL.md wins.","Rebuild the zip so SKILL.md and manifest stay in sync, then re-upload."],"exampleFix":"// before: manifest.json has \"name\":\"translate\" but SKILL.md has name: translator\n// after — align both:\n---\n# SKILL.md frontmatter\nname: translate\n---\n// manifest.json\n{\"name\":\"translate\",\"version\":\"1.0.0\"}","handlingStrategy":"validation","validationCode":"// Before register(), assert manifest name matches SKILL.md frontmatter name\nString manifestName = (String) new ObjectMapper().readValue(manifestJson, Map.class).get(\"name\");\nif (manifestName != null && !manifestName.isBlank()) {\n    String pkgName = readSkillMdFrontmatterName(packageZipBytes); // parse SKILL.md frontmatter\n    if (!manifestName.equals(pkgName)) {\n        throw new IllegalStateException(\"manifest name \" + manifestName + \" != SKILL.md name \" + pkgName);\n    }\n}","typeGuard":"// Java: confirm manifest carries a usable name or is intentionally omitted\nstatic boolean manifestNameConsistentOrAbsent(Map<String,Object> manifest, String skillMdName) {\n    Object n = manifest.get(\"name\");\n    return n == null || n.toString().isBlank() || n.toString().equals(skillMdName);\n}","tryCatchPattern":"try { skillRegistryService.register(manifest, pkg); }\ncatch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"does not match\")) { /* align names, re-upload */ }\n    else throw e;\n}","preventionTips":["Single-source the skill name from one config and inject it into both the manifest JSON and the SKILL.md frontmatter at build time.","In CI, parse SKILL.md frontmatter and assert it equals the manifest name before publishing."],"tags":["java","conductor","skill-registry","validation","multipart-upload"],"backgroundTag":null,"analyzedSha":"cf7c3e4a8adfb158be778ab1ec525323c363cd3a","analyzedAt":"2026-08-14T03:33:19.897Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}