paperclipai/paperclip · error
Explicit skill input must reference a unique assigned…
Error message
Explicit skill input must reference a unique assigned runtime skill
What it means
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.
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_-]+$/
Example fix
// before
{ type: "skill", name: "My Skill", path: "/custom/SKILL.md" }
// after
const assigned = context.skills.find(s => s.runtimeName === "my-skill");
{ type: "skill", name: assigned.runtimeName, path: resolve(assigned.bundle.rootPath, "SKILL.md") } Defensive patterns
Strategy: validation
Validate before calling
const assigned = context.skills?.find(s => s.runtimeName === input.name);
const ok = assigned
&& /^[a-zA-Z0-9_-]+$/.test(assigned.runtimeName)
&& resolve(input.path) === resolve(assigned.bundle.rootPath, "SKILL.md");
if (!ok) throw new Error(`Skill ${input.name} is not a uniquely assigned runtime skill`); Type guard
function isAssignedSkill(input, context) {
return context.skills.some(s => s.runtimeName === input.name
&& /^[a-zA-Z0-9_-]+$/.test(s.runtimeName));
} Prevention
- 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_-])
When it happens
Trigger: 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_-].
Common situations: 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.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- invalid_skill_document
- native_adopted_runner_state_directory_required
- Paperclip Runner currently supports Codex only with…
- railway_authorization_required
- railway_target_mismatch
AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-09-18).
Data as JSON: /api/errors/25415be61ddf16e2.
Report an issue: GitHub.
Appendix: source
Thrown at packages/paperclip-runner/src/live/runnerd-codex-transport.ts:6632
});
/** Map controller asset paths to the assigned copy on the provider filesystem. */
export function resolveRunnerdCodexSkillInputs(
inputs: Record<string, unknown>[],
context: NativeRuntimeContextSnapshot | null,
codexHome: string,
): Array<{ type: "skill"; name: string; path: string }> {
if (inputs.length > 64) throw new Error("Too many explicit skill inputs");
const seen = new Set<string>();
return inputs.map((input) => {
const assigned = context?.skills.find((skill) => skill.runtimeName === input.name);
if (
!assigned || !/^[a-zA-Z0-9_-]+$/.test(assigned.runtimeName)
|| input.path !== resolve(assigned.bundle.rootPath, "SKILL.md")
|| seen.has(assigned.runtimeName)
) {
throw new Error("Explicit skill input must reference a unique assigned runtime skill");
}
seen.add(assigned.runtimeName);
return {
type: "skill",
name: assigned.runtimeName,
path: resolve(codexHome, "skills", assigned.runtimeName, "SKILL.md"),
};
});
}
View on GitHub (pinned to 3f1d897a7c)