larksuite/cli · error
%w: %v
Error message
%w: %v
What it means
ReadState in internal/skillscheck/state.go wraps ErrUnreadableState when the persisted skills state file exists but cannot be parsed. It first tries a generic map unmarshal (line 50); if the file is not a JSON object at all, this error is returned with the json.Unmarshal cause via %w/%v. It signals corrupted or non-JSON state data, not a missing file (missing files are handled upstream).
Source
Thrown at internal/skillscheck/state.go:50
UpdatedAt string `json:"updated_at"`
}
func statePath() string {
return filepath.Join(core.GetBaseConfigDir(), stateFile)
}
func ReadState() (*SkillsState, bool, error) {
data, err := vfs.ReadFile(statePath())
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
return nil, false, nil
}
return nil, false, err
}
var raw map[string]interface{}
if err := json.Unmarshal(data, &raw); err != nil {
return nil, false, fmt.Errorf("%w: %v", ErrUnreadableState, err)
}
var state SkillsState
if err := json.Unmarshal(data, &state); err != nil {
return nil, false, fmt.Errorf("%w: %v", ErrUnreadableState, err)
}
return &state, true, nil
}
func WriteState(state SkillsState) error {
state.ensureNonNilSlices()
if err := vfs.MkdirAll(core.GetBaseConfigDir(), 0o700); err != nil {
return err
}
data, err := json.MarshalIndent(state, "", " ")
if err != nil {
return errView on GitHub (pinned to 7fd6ef3c07)
Solutions
- Inspect the state file and fix or remove invalid JSON characters; deleting the corrupt file lets skillscheck regenerate it
- Validate the file with `jq . <state-file>` to pinpoint the syntax error
- Restore the file from backup or let WriteState recreate it on the next successful run
- If writes are being truncated, check disk space and ensure writes complete atomically
Example fix
// before
$ cat ~/.lark/skills-state.json
{"lastRun":"2026-09-04" // truncated
// after (valid object)
{"lastRun":"2026-09-04","skills":[]} Defensive patterns
Strategy: try-catch
Validate before calling
// before calling ReadState
if data, err := os.ReadFile(statePath); err == nil {
if !json.Valid(data) {
// state file is corrupt; remove or repair before ReadState
os.Remove(statePath)
}
} Type guard
func isUnreadableState(err error) bool {
return errors.Is(err, skillscheck.ErrUnreadableState)
} Try / catch
state, ok, err := skillscheck.ReadState(path)
if err != nil {
if errors.Is(err, skillscheck.ErrUnreadableState) {
// corrupt file: log and fall back to fresh state
os.Remove(path)
state, ok, err = skillscheck.ReadState(path)
}
if err != nil { return err }
} Prevention
- Write the state file atomically (temp file + rename) so crashes never leave truncated JSON
- Never hand-edit the state file; regenerate it instead
- Monitor disk space on the host holding the state file
- Periodically validate the file with `jq empty` in health checks
When it happens
Trigger: Calling ReadState when the state file contains malformed JSON (e.g. truncated write, binary data, or a JSON array/string instead of an object), so the first json.Unmarshal into map[string]interface{} fails.
Common situations: Disk full or crash mid-write leaving a truncated state file; a user hand-edited the state file into invalid JSON; the file was replaced by another tool writing a non-object JSON value; encoding mismatch (e.g. UTF-16 file saved by an editor).
Related errors
- lark-cli stdout was not JSON: {snippet}
- lark-cli returned a non-object JSON payload
- stored token data is corrupt
- malformed config
- skills state is unreadable
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/eb4ce427fd462101.
Report an issue: GitHub.