{"record":{"id":"25415be61ddf16e2","repo":"paperclipai/paperclip","slug":"explicit-skill-input-must-reference-a-unique-assigned","errorCode":null,"errorMessage":"Explicit skill input must reference a unique assigned runtime skill","messagePattern":"Explicit skill input must reference a unique assigned runtime skill","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/paperclip-runner/src/live/runnerd-codex-transport.ts","lineNumber":6632,"sourceCode":"});\n\n\n/** Map controller asset paths to the assigned copy on the provider filesystem. */\nexport function resolveRunnerdCodexSkillInputs(\n  inputs: Record<string, unknown>[],\n  context: NativeRuntimeContextSnapshot | null,\n  codexHome: string,\n): Array<{ type: \"skill\"; name: string; path: string }> {\n  if (inputs.length > 64) throw new Error(\"Too many explicit skill inputs\");\n  const seen = new Set<string>();\n  return inputs.map((input) => {\n    const assigned = context?.skills.find((skill) => skill.runtimeName === input.name);\n    if (\n      !assigned || !/^[a-zA-Z0-9_-]+$/.test(assigned.runtimeName)\n      || input.path !== resolve(assigned.bundle.rootPath, \"SKILL.md\")\n      || seen.has(assigned.runtimeName)\n    ) {\n      throw new Error(\"Explicit skill input must reference a unique assigned runtime skill\");\n    }\n    seen.add(assigned.runtimeName);\n    return {\n      type: \"skill\",\n      name: assigned.runtimeName,\n      path: resolve(codexHome, \"skills\", assigned.runtimeName, \"SKILL.md\"),\n    };\n  });\n}\n","sourceCodeStart":6614,"sourceCodeEnd":6642,"githubUrl":"https://github.com/paperclipai/paperclip/blob/3f1d897a7c018d76563a21c6e39c3c9b03933622/packages/paperclip-runner/src/live/runnerd-codex-transport.ts#L6614-L6642","documentation":"This error is thrown when an agent supplies an explicit skill input that does not resolve to exactly one runtime skill already assigned to the run. The transport validates the runtime name is a slug, the supplied path points at the assigned bundle's SKILL.md, and the skill has not been referenced before in this invocation (uniqueness). Any mismatch means the runner would mount a skill the run is not authorized to use, so it fails fast.","triggerScenarios":"Calling the codex transport with an explicit skill input whose `name` does not match any `context.skills[].runtimeName`; passing a `path` other than `resolve(assigned.bundle.rootPath, 'SKILL.md')`; passing a path outside the bundle (e.g. a custom SKILL.md location); referencing the same runtime skill twice in one input list; or a runtimeName containing characters outside [a-zA-Z0-9_-].","commonSituations":"Hand-written runner configs that guess skill names instead of copying assigned runtimeName values; moving or renaming a skill bundle so the SKILL.md path no longer matches; duplicating a skill entry in a fixture to test multiple invocations; typos or spaces in runtime names.","solutions":["Print `context.skills` and use the exact `runtimeName` of an assigned skill as the input `name`","Set the input `path` to `resolve(assigned.bundle.rootPath, 'SKILL.md')` — never a custom or copied path","Remove duplicate entries so each assigned runtime skill is referenced at most once per invocation","Rename the skill so its runtimeName matches /^[a-zA-Z0-9_-]+$/"],"exampleFix":"// before\n{ type: \"skill\", name: \"My Skill\", path: \"/custom/SKILL.md\" }\n// after\nconst assigned = context.skills.find(s => s.runtimeName === \"my-skill\");\n{ type: \"skill\", name: assigned.runtimeName, path: resolve(assigned.bundle.rootPath, \"SKILL.md\") }","handlingStrategy":"validation","validationCode":"const assigned = context.skills?.find(s => s.runtimeName === input.name);\nconst ok = assigned\n  && /^[a-zA-Z0-9_-]+$/.test(assigned.runtimeName)\n  && resolve(input.path) === resolve(assigned.bundle.rootPath, \"SKILL.md\");\nif (!ok) throw new Error(`Skill ${input.name} is not a uniquely assigned runtime skill`);","typeGuard":"function isAssignedSkill(input, context) {\n  return context.skills.some(s => s.runtimeName === input.name\n    && /^[a-zA-Z0-9_-]+$/.test(s.runtimeName));\n}","tryCatchPattern":null,"preventionTips":["Always source skill names from context.skills[].runtimeName, never from memory or docs","Reference each assigned skill at most once per invocation","Point paths at assigned.bundle.rootPath/SKILL.md rather than custom locations","Keep runtime names slug-shaped ([a-zA-Z0-9_-])"],"tags":["skills","validation","runner","authorization"],"backgroundTag":"invalid-argument-value","analyzedSha":"3f1d897a7c018d76563a21c6e39c3c9b03933622","analyzedAt":"2026-09-18T08:03:59.046Z","contentChangedAt":"2026-09-18T08:03:59.046Z","schemaVersion":2},"datasetVersion":"2026-09-22T11:17:16.035Z"}