{"record":{"id":"b1fad83e8daf50cb","repo":"sipeed/picoclaw","slug":"failed-to-persist-skill-metadata-w","errorCode":null,"errorMessage":"✗ failed to persist skill metadata: %w","messagePattern":"✗ failed to persist skill metadata: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/picoclaw/internal/skills/helpers.go","lineNumber":124,"sourceCode":"\n\tif !workspaceHasValidSkillDirectory(workspace, dirName) {\n\t\t_ = os.RemoveAll(targetDir)\n\t\treturn fmt.Errorf(\"✗ failed to install skill: registry archive for %q is not a valid skill\", target)\n\t}\n\n\tnormalizedSlug, registryURL := skills.BuildInstallMetadataForRegistryInstance(registry, target, result.Version)\n\tinstalledAt := time.Now().UnixMilli()\n\tif err := writeInstalledSkillOriginMeta(targetDir, installedSkillOriginMeta{\n\t\tVersion:          1,\n\t\tOriginKind:       \"third_party\",\n\t\tRegistry:         registry.Name(),\n\t\tSlug:             normalizedSlug,\n\t\tRegistryURL:      registryURL,\n\t\tInstalledVersion: result.Version,\n\t\tInstalledAt:      installedAt,\n\t}); err != nil {\n\t\t_ = os.RemoveAll(targetDir)\n\t\treturn fmt.Errorf(\"✗ failed to persist skill metadata: %w\", err)\n\t}\n\n\tfmt.Printf(\"\\u2713 Skill '%s' v%s installed successfully!\\n\", dirName, result.Version)\n\tif result.Summary != \"\" {\n\t\tfmt.Printf(\"  %s\\n\", result.Summary)\n\t}\n\n\treturn nil\n}\n\nfunc writeInstalledSkillOriginMeta(targetDir string, meta installedSkillOriginMeta) error {\n\tdata, err := json.MarshalIndent(meta, \"\", \"  \")\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn fileutil.WriteFileAtomic(filepath.Join(targetDir, \".skill-origin.json\"), data, 0o600)\n}\n","sourceCodeStart":106,"sourceCodeEnd":142,"githubUrl":"https://github.com/sipeed/picoclaw/blob/49183d7e8daed0dba89ddbb6fcb60089401d9680/cmd/picoclaw/internal/skills/helpers.go#L106-L142","documentation":"The skill files installed, but writing the origin metadata (.skill-origin.json under the skill directory, written atomically via fileutil.WriteFileAtomic) failed — a marshal error or a disk write failure. The install is rolled back with os.RemoveAll so nothing half-installed remains.","triggerScenarios":"Disk full or quota exceeded, write permission lost mid-install, or the freshly created targetDir removed/locked concurrently, causing writeInstalledSkillOriginMeta to fail at helpers.go:124.","commonSituations":"Disk quota exhausted during install, an antivirus/filesystem watcher locking the new directory on some platforms, or the workspace on a flaky network mount.","solutions":["Check free space and quota on the workspace filesystem (df and quota).","Verify write permission on <workspace>/skills/<dirName>.","Retry after freeing space or remounting; the rollback makes retries safe.","If it recurs on a single machine, check antivirus/filesystem-watcher interference."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"probe := filepath.Join(workspace, \".meta-write-probe\")\nif err := os.WriteFile(probe, []byte(\"ok\"), 0o644); err != nil {\n    return fmt.Errorf(\"workspace not writable: %w\", err)\n}\nos.Remove(probe)","typeGuard":null,"tryCatchPattern":"if err := writeInstalledSkillOriginMeta(targetDir, meta); err != nil {\n    if isTransientFS(err) { // EIO, ENOSPC cleared after cleanup\n        return retryWithBackoff()\n    }\n    return fmt.Errorf(\"failed to persist skill metadata: %w\", err)\n}","preventionTips":["Monitor free space on the filesystem hosting the workspace.","Keep the workspace off network mounts where possible.","Retry the install once — the automatic rollback makes retries safe."],"tags":["filesystem","metadata","install","go"],"backgroundTag":null,"analyzedSha":"49183d7e8daed0dba89ddbb6fcb60089401d9680","analyzedAt":"2026-08-15T21:55:41.315Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}