{"record":{"id":"d2d52435c45ce318","repo":"microsoft/aspire","slug":"skill-skill-name-does-not-define-installable-files","errorCode":null,"errorMessage":"Skill '{skill.Name}' does not define installable files.","messagePattern":"Skill '(.+?)' does not define installable files\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Cli/Commands/AgentInitCommand.cs","lineNumber":771,"sourceCode":"\n    private static async Task<IReadOnlyList<SkillAssetFile>> GetSkillFilesAsync(SkillDefinition skill, AspireSkillsBundle? aspireSkillsBundle, CancellationToken cancellationToken)\n    {\n        if (skill.SkillContent is not null)\n        {\n            return [new SkillAssetFile(\"SKILL.md\", skill.SkillContent)];\n        }\n\n        if (skill.SourceKind is SkillSourceKind.AspireSkillsBundle)\n        {\n            if (aspireSkillsBundle is null)\n            {\n                throw new InvalidOperationException($\"Aspire skills bundle was not resolved for skill '{skill.Name}'.\");\n            }\n\n            return await aspireSkillsBundle.GetSkillFilesAsync(skill, cancellationToken);\n        }\n\n        throw new InvalidOperationException($\"Skill '{skill.Name}' does not define installable files.\");\n    }\n\n    private sealed record InstalledSkillSummaryItem(string SkillName, string DisplayLocation);\n\n    private readonly record struct SkillInstallResult(bool Succeeded, InstalledSkillSummaryItem? UpdatedSkill);\n}\n\ninternal readonly record struct AgentInitExecutionResult(\n    int ExitCode,\n    IReadOnlyList<SkillLocation> SelectedLocations,\n    IReadOnlyList<SkillDefinition> SelectedSkills);\n","sourceCodeStart":753,"sourceCodeEnd":783,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Cli/Commands/AgentInitCommand.cs#L753-L783","documentation":"GetSkillFilesAsync ends with a terminal throw for skills that match none of the supported source kinds (e.g. not an Aspire skills bundle or another file-providing source) yet carry no installable files. The library throws because it cannot produce the file set the agent-init install step requires for this skill.","triggerScenarios":"Invoking GetSkillFilesAsync with a skill whose SourceKind is a kind that does not implement GetSkillFilesAsync and that defines no installable file entries — e.g. a metadata-only or inline/documented skill with no files.","commonSituations":"A custom or user-defined skill in the agent-init skill configuration that only provides instructions (no files), but is processed by the file-install path; misconfigured skill manifest missing its file definitions.","solutions":["Add installable file definitions to the skill so it maps to a supported file-providing source kind","Exclude the file-less skill from the file-install path (it may only need registration, not file installation)","Verify the skill's manifest declares the correct SourceKind"],"exampleFix":"// before\nvar files = await GetSkillFilesAsync(skill, aspireSkillsBundle, cancellationToken);\n// after\nif (skill.SourceKind is not (SkillSourceKind.AspireSkillsBundle or SkillSourceKind.LocalFiles))\n{\n    continue; // file-less skill: register without installing files\n}\nvar files = await GetSkillFilesAsync(skill, aspireSkillsBundle, cancellationToken);","handlingStrategy":"validation","validationCode":"if (!skillHasInstallableFiles(skill))\n{\n    continue; // file-less skill: skip the file-install path\n}","typeGuard":"var hasFiles = skill.SourceKind is SkillSourceKind.AspireSkillsBundle or SkillSourceKind.LocalFiles;","tryCatchPattern":"try\n{\n    files = await GetSkillFilesAsync(skill, bundle, ct);\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"does not define installable files\"))\n{\n    logger.LogInformation(\"Skill {Skill} has no files; registering only\", skill.Name);\n}","preventionTips":["Only pass file-providing skills to GetSkillFilesAsync","Check the skill manifest for file definitions before install","Register instruction-only skills through a separate path"],"tags":["cli","aspire","skills"],"backgroundTag":"unsupported-operation","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T09:17:21.228Z"}