{"record":{"id":"4e6c1d9bb5fb35ef","repo":"Hmbown/CodeWhale","slug":"skill-is-not-an-import-candidate","errorCode":null,"errorMessage":"skill is not an import candidate","messagePattern":"skill is not an import candidate","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/skills/mutation.rs","lineNumber":670,"sourceCode":"    }\n    if source_skill.path_unsafe {\n        bail!(\"refusing to import unsafe external skill package\");\n    }\n\n    let owned_snap = scan_with_configured(\n        ctx.workspace,\n        ctx.home,\n        ctx.configured_skills_dir,\n        SkillAuditMode::OwnedOnly,\n        None,\n    );\n    let owned_has_name = owned_snap\n        .skills\n        .iter()\n        .any(|s| s.id.canonical_name == source_id.canonical_name);\n\n    if !owned_has_name && !source_skill.import_candidate {\n        bail!(\"skill is not an import candidate\");\n    }\n\n    let before = verify_expected_digest(&source_path, Some(&expected_digest))?;\n\n    let skills_dir = prepare_owned_target(ctx.workspace, ctx.home, target)?;\n    let anchor = owned_anchor(ctx.workspace, ctx.home, target)?;\n\n    let want_kind = match target {\n        SkillTargetScope::Project => SkillRootKind::CodeWhaleProject,\n        SkillTargetScope::Global => SkillRootKind::CodeWhaleGlobal,\n    };\n    let existing_in_target: Vec<&AuditedSkill> = owned_snap\n        .skills\n        .iter()\n        .filter(|s| s.id.canonical_name == source_id.canonical_name)\n        .filter(|s| s.root.kind == want_kind)\n        .collect();\n","sourceCodeStart":652,"sourceCodeEnd":688,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/skills/mutation.rs#L652-L688","documentation":"Thrown when `import_external` would silently import a skill the caller never opted into: the target owned scope does not already contain the canonical name, and the audit did not mark the skill as `import_candidate`. Import is either explicit-candidate-only or a deduplicating AlreadyPresent no-op.","triggerScenarios":"Calling `import_external` where the owned snapshot has no skill matching `source_id.canonical_name` and `source_skill.import_candidate` is false — i.e. the external skill was never flagged as an import suggestion by the audit.","commonSituations":"Pointing import at an arbitrary external skill that was never surfaced as a candidate; a stale audit predating the candidate flag; passing a `SkillTargetScope` different from the one that holds the name (so `owned_has_name` is false).","solutions":["Import the skill through the flow that marks it as an import candidate (accept it from the audit/suggestion listing) instead of calling import directly.","Re-run the audit so `import_candidate` is refreshed, then retry.","Use the correct `SkillTargetScope` where the skill's canonical name already exists if the intent was to refresh an existing import."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"let owned_has_name = owned_snap.skills.iter().any(|s| s.id.canonical_name == source_id.canonical_name);\nif !owned_has_name && !source_skill.import_candidate {\n    return Err(anyhow!(\"skill is not an import candidate\"));\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Import only skills surfaced as candidates by the audit.","Refresh the audit before importing so import_candidate is current.","Pass the SkillTargetScope that actually holds the skill's canonical name when refreshing."],"tags":["skills","import","validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}