{"record":{"id":"16c267cb72b06691","repo":"conductor-oss/conductor","slug":"skill-package-not-found-name-version","errorCode":null,"errorMessage":"Skill package not found: {name}@{version}","messagePattern":"Skill package not found: (.+?)@(.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"agentspan/src/main/java/org/conductoross/conductor/ai/agentspan/runtime/service/SkillRegistryService.java","lineNumber":897,"sourceCode":"        return matcher.group(2).trim();\n    }\n\n    private boolean packageExists(SkillDetail detail) {\n        String handle = detail.getPackageFileHandleId();\n        if (handle == null || handle.isBlank()) {\n            return false;\n        }\n        try {\n            return packageStore.exists(handle);\n        } catch (RuntimeException ignored) {\n            return false;\n        }\n    }\n\n    private byte[] packageBytes(SkillDetail detail) {\n        String handle = detail.getPackageFileHandleId();\n        if (handle == null || handle.isBlank()) {\n            throw new IllegalArgumentException(\n                    \"Skill package not found: \" + detail.getName() + \"@\" + detail.getVersion());\n        }\n        return packageStore.read(handle);\n    }\n\n    private void deletePackage(SkillDetail detail) {\n        String handle = detail.getPackageFileHandleId();\n        if (handle != null && !handle.isBlank()) {\n            try {\n                packageStore.delete(handle);\n            } catch (IllegalArgumentException ignored) {\n                // Legacy records used synthetic handles before the package store existed.\n            }\n        }\n    }\n\n    private String normalizeEntryName(String name) {\n        String normalized = name.replace('\\\\', '/');","sourceCodeStart":879,"sourceCodeEnd":915,"githubUrl":"https://github.com/conductor-oss/conductor/blob/cf7c3e4a8adfb158be778ab1ec525323c363cd3a/agentspan/src/main/java/org/conductoross/conductor/ai/agentspan/runtime/service/SkillRegistryService.java#L879-L915","documentation":"Thrown by packageBytes when a SkillDetail has a null or blank `packageFileHandleId` — the opaque ID used to read the stored package blob from the SkillPackageStore. The metadata record exists, but the blob it points at is missing, so any operation that needs the actual zip bytes (download, file listing, repackaging) refuses rather than returning garbage.","triggerScenarios":"Calling an API that materializes package bytes (download, list files, read file content) for a skill whose metadata row survived but whose blob was deleted, never written, or migrated incompletely from the legacy synthetic-handle scheme.","commonSituations":"Partial migration from pre-package-store records; the underlying object store was cleared but the DAO table was not; a delete partially failed and left the metadata row; a manually-inserted test row omitted the handle.","solutions":["Re-upload the skill package so a fresh blob handle is written and the metadata row's packageFileHandleId is populated.","If this is a legacy record, delete the orphan metadata row and re-publish.","Verify the SkillPackageStore backend is reachable and the DAO write path sets the handle on insert."],"exampleFix":"// before: metadata row with packageFileHandleId = null\n// re-publish via the upload API\nPOST /api/ai/skills/packages  (multipart with the corrected zip)\n// after: row carries a real handle id and packageBytes() resolves","handlingStrategy":"validation","validationCode":"// Verify a skill has a non-blank package handle before using it.\nboolean hasStoredPackage(SkillDetail d) {\n    String h = d.getPackageFileHandleId();\n    return h != null && !h.isBlank();\n}","typeGuard":"boolean isResolvable(SkillDetail d, SkillPackageStore store) {\n    String h = d.getPackageFileHandleId();\n    return h != null && !h.isBlank() && store.exists(h);\n}","tryCatchPattern":"try {\n    byte[] bytes = skillRegistry.packageBytes(detail);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().startsWith(\"Skill package not found\")) {\n        return notFound(e.getMessage()); // 404, prompt re-upload\n    }\n    throw e;\n}","preventionTips":["Re-upload skills after a store migration and verify packageFileHandleId is set.","Run a consistency check (metadata row -> blob exists) periodically.","Treat a missing handle as a data-integrity incident; do not silently skip."],"tags":["skill-registry","package-store","data-integrity","missing-blob"],"backgroundTag":null,"analyzedSha":"cf7c3e4a8adfb158be778ab1ec525323c363cd3a","analyzedAt":"2026-08-14T03:33:19.897Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}