{"record":{"id":"baf1ccff90a862a6","repo":"googleapis/mcp-toolbox","slug":"error-writing-skill-md-w","errorCode":null,"errorMessage":"error writing SKILL.md: %w","messagePattern":"error writing SKILL\\.md: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/internal/skills/command.go","lineNumber":236,"sourceCode":"\n\t\t\tscriptFilename := filepath.Join(scriptsPath, fmt.Sprintf(\"%s.js\", toolName))\n\t\t\tif err := os.WriteFile(scriptFilename, []byte(scriptContent), 0755); err != nil {\n\t\t\t\terrMsg := fmt.Errorf(\"error writing script %s: %w\", scriptFilename, err)\n\t\t\t\topts.Logger.ErrorContext(ctx, errMsg.Error())\n\t\t\t\treturn errMsg\n\t\t\t}\n\t\t}\n\n\t\t// Generate SKILL.md\n\t\tskillContent, err := generateSkillMarkdown(skillName, content.description, cmd.additionalNotes, allTools, parser.EnvVars)\n\t\tif err != nil {\n\t\t\terrMsg := fmt.Errorf(\"error generating SKILL.md content: %w\", err)\n\t\t\topts.Logger.ErrorContext(ctx, errMsg.Error())\n\t\t\treturn errMsg\n\t\t}\n\t\tskillMdPath := filepath.Join(skillPath, \"SKILL.md\")\n\t\tif err := os.WriteFile(skillMdPath, []byte(skillContent), 0644); err != nil {\n\t\t\terrMsg := fmt.Errorf(\"error writing SKILL.md: %w\", err)\n\t\t\topts.Logger.ErrorContext(ctx, errMsg.Error())\n\t\t\treturn errMsg\n\t\t}\n\n\t\topts.Logger.InfoContext(ctx, fmt.Sprintf(\"Successfully generated skill '%s' with %d tools.\", skillName, len(allTools)))\n\t}\n\n\treturn nil\n}\n\n// resolveSkillName returns the explicit --name when set. Otherwise, in the\n// single-skill modes it defaults to the --group or --toolset name, and for\n// prebuilt generation it defaults to the config name when exactly one\n// --prebuilt config is given. Any other case requires --name.\nfunc resolveSkillName(name, group, toolset string, prebuiltConfigs []string) (string, error) {\n\tif name != \"\" {\n\t\treturn name, nil\n\t}","sourceCodeStart":218,"sourceCodeEnd":254,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/cmd/internal/skills/command.go#L218-L254","documentation":"This error wraps a failure from os.WriteFile when writing the generated SKILL.md file into the skill directory. The markdown content was generated successfully, but persisting it to disk failed — a filesystem-level problem analogous to error 66 but targeting SKILL.md specifically.","triggerScenarios":"Running `toolbox skills` when os.WriteFile(skillMdPath, ...) fails — the skill directory is missing, not writable, SKILL.md already exists with restrictive permissions, or the filesystem is full/read-only.","commonSituations":"The skill directory exists but is owned by root or another user; SKILL.md is checked into git with read-only mode or was edited with restrictive permissions; writing into a read-only container volume or a full disk.","solutions":["Check permissions on the skill directory and any existing SKILL.md (ls -l) and chmod/chown as needed","Remove or fix a pre-existing SKILL.md with restrictive permissions","Re-run with a different --output location you have write access to","Free disk space or remount read-write if the filesystem is full or read-only"],"exampleFix":"// before\n-r--r--r-- SKILL.md  # read-only file -> write fails\n// after\nchmod u+w SKILL.md && toolbox skills --name my-skill ...","handlingStrategy":"validation","validationCode":"# Ensure the skill dir exists and SKILL.md is writable before generating\nmkdir -p \"$OUT/skills/my-skill\"\nif [ -e \"$OUT/skills/my-skill/SKILL.md\" ] && [ ! -w \"$OUT/skills/my-skill/SKILL.md\" ]; then\n  chmod u+w \"$OUT/skills/my-skill/SKILL.md\" || exit 1\nfi","typeGuard":null,"tryCatchPattern":"try {\n  execSync(\"toolbox skills --name my-skill\", { stdio: \"inherit\" });\n} catch (e) {\n  if (String(e.stderr).includes(\"error writing SKILL.md\")) {\n    console.error(\"Could not write SKILL.md; fix permissions or output path:\", e.stderr);\n  } else { throw e; }\n}","preventionTips":["Fix git-tracked generated files to writable modes (git config core.fileMode checks)","Pre-create the skill directory with correct ownership","Avoid writing skills into read-only container mounts","Check disk space when generating many skills in one run"],"tags":["go","cli","filesystem","permissions","write-file"],"backgroundTag":"file-write-permission-denied","analyzedSha":"8cc6e09de2ad7b8bffc77751799585a1401a48eb","analyzedAt":"2026-09-05T01:10:36.887Z","contentChangedAt":"2026-09-05T01:10:36.887Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}