{"record":{"id":"e6788dd66c665552","repo":"larksuite/cli","slug":"skills-synced-but-state-not-written-w","errorCode":null,"errorMessage":"skills synced but state not written: %w","messagePattern":"skills synced but state not written: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/skillscheck/sync.go","lineNumber":513,"sourceCode":"\t\tAdded:           plan.Added,\n\t\tSkippedDeleted:  plan.SkippedDeleted,\n\t\tWarning:         warning,\n\t\tLayout:          layout,\n\t\tForce:           opts.Force,\n\t}\n\tstate := SkillsState{\n\t\tVersion:               opts.Version,\n\t\tLayout:                layout,\n\t\tOfficialSkills:        plan.OfficialSkills,\n\t\tOfficialSkillsUnknown: officialUnknown,\n\t\tUpdatedSkills:         plan.ToUpdate,\n\t\tAddedOfficialSkills:   plan.Added,\n\t\tSkippedDeletedSkills:  plan.SkippedDeleted,\n\t\tUpdatedAt:             opts.Now().UTC().Format(time.RFC3339),\n\t}\n\tif err := WriteState(state); err != nil {\n\t\tresult.Action = \"failed\"\n\t\tresult.Err = fmt.Errorf(\"skills synced but state not written: %w\", err)\n\t}\n\treturn result\n}\n\nfunc hasInstalledSkill(installed []installedSkill, name string) bool {\n\tfor _, skill := range installed {\n\t\tif skill.Name == name {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfunc resultDetail(result *selfupdate.NpmResult) string {\n\tif result == nil {\n\t\treturn \"\"\n\t}\n\tparts := []string{}","sourceCodeStart":495,"sourceCodeEnd":531,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/internal/skillscheck/sync.go#L495-L531","documentation":"finishSync in internal/skillscheck/sync.go returns this error when skills were successfully downloaded/installed but persisting the resulting SkillsState via WriteState failed. The CLI reports Action 'failed' even though the on-disk skills are current, because the recorded state (layout, versions, timestamps) could not be written. This causes redundant re-syncs on the next run since state tracking is lost.","triggerScenarios":"SyncSkills or fallbackSeparate reaching finishSync after a successful plan/install, and WriteState(state) returning a non-nil error while persisting the skills state file.","commonSituations":"Disk full or quota exceeded; the CLI config/state directory is read-only or owned by another user (e.g. ran with sudo once, now ~/.lark-cli files are root-owned); antivirus or backup software locks the state file; a corrupted state file prevents rewriting; container with a read-only home volume.","solutions":["Check disk space (df -h) and free space if full","Fix ownership/permissions of the state file and its directory (ls -la on the config dir; chown back to your user)","Verify the config/state directory is writable (touch a test file in it)","Delete the corrupted state file and re-run the sync so it is regenerated"],"exampleFix":"// before\nWriteState(state) -> error: open ~/.lark-cli/skills_state.json: permission denied\n\n// after\nsudo chown -R $(whoami) ~/.lark-cli\nlark-cli skills sync  # state writes succeed","handlingStrategy":"validation","validationCode":"// verify state dir is writable before syncing\nstateDir := os.Getenv(\"LARKSUITE_CLI_CONFIG_DIR\")\nif stateDir == \"\" {\n    home, _ := os.UserHomeDir()\n    stateDir = filepath.Join(home, \".lark-cli\")\n}\ntest := filepath.Join(stateDir, \".write-test\")\nif err := os.WriteFile(test, nil, 0o600); err != nil {\n    return fmt.Errorf(\"state dir not writable: %w\", err)\n}\nos.Remove(test)","typeGuard":null,"tryCatchPattern":"res := syncSkills(ctx)\nif res.Action == \"failed\" && strings.Contains(res.Err.Error(), \"state not written\") {\n    // skills are current; only state persistence failed\n    log.Printf(\"re-syncing needed later: %v\", res.Err)\n    if errors.Is(res.Err, os.ErrPermission) { /* fix ownership of ~/.lark-cli */ }\n}","preventionTips":["Keep ~/.lark-cli owned by your regular user; avoid mixing sudo and normal runs","Monitor disk space on the volume holding your home/config directory","Exclude the config dir from lockers (AV/backup sync tools) that grab files mid-write","Delete stale or corrupted state files before major version upgrades"],"tags":["filesystem","state-persistence","permissions"],"backgroundTag":"state-write-failed","analyzedSha":"7fd6ef3c07182257ce776cdc5a614e122d5bd4b3","analyzedAt":"2026-09-04T21:17:44.649Z","contentChangedAt":"2026-09-04T21:17:44.649Z","schemaVersion":2},"datasetVersion":"2026-09-12T02:17:10.037Z"}