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 err

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Inspect the state file and fix or remove invalid JSON characters; deleting the corrupt file lets skillscheck regenerate it
  2. Validate the file with `jq . <state-file>` to pinpoint the syntax error
  3. Restore the file from backup or let WriteState recreate it on the next successful run
  4. 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

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


AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04). Data as JSON: /api/errors/eb4ce427fd462101. Report an issue: GitHub.