plandex-ai/plandex · error

error unmarshalling JSON file: %v

Error message

error unmarshalling JSON file: %v

What it means

ModelSettingsCheckLocalChanges unmarshals the settings file contents into *shared.ClientModelPackSchemaRoles. This error wraps json.Unmarshal failure: the file exists and is readable but is not valid JSON for the expected schema, so local changes cannot be hashed or compared.

Source

Thrown at app/cli/lib/model_settings.go:57

	if !exists {
		return ModelSettingsCheckLocalChangesResult{}, nil
	}

	lastSavedHash, err := os.ReadFile(hashPath)
	if err != nil && !os.IsNotExist(err) {
		return ModelSettingsCheckLocalChangesResult{}, fmt.Errorf("error reading hash file: %v", err)
	}

	localJsonData, err := os.ReadFile(path)
	if err != nil {
		return ModelSettingsCheckLocalChangesResult{}, fmt.Errorf("error reading JSON file: %v", err)
	}

	var clientModelPackSchemaRoles *shared.ClientModelPackSchemaRoles
	err = json.Unmarshal(localJsonData, &clientModelPackSchemaRoles)
	if err != nil {
		return ModelSettingsCheckLocalChangesResult{}, fmt.Errorf("error unmarshalling JSON file: %v", err)
	}

	currentHash, err := clientModelPackSchemaRoles.ToModelPackSchemaRoles().Hash()
	if err != nil {
		return ModelSettingsCheckLocalChangesResult{}, fmt.Errorf("error hashing model pack: %v", err)
	}

	modelPackSchemaRoles := clientModelPackSchemaRoles.ToModelPackSchemaRoles()

	return ModelSettingsCheckLocalChangesResult{
		HasLocalChanges:           currentHash != string(lastSavedHash),
		LocalModelPackSchemaRoles: &modelPackSchemaRoles,
	}, nil
}

func WriteModelSettingsFile(path string, originalSettings *shared.PlanSettings) error {
	err := os.MkdirAll(filepath.Dir(path), 0755)
	if err != nil {

View on GitHub (pinned to e2d772072e)

Solutions

  1. Validate the file with `jq . <settingsPath>` or a JSON linter and fix the syntax error reported by the wrapped message.
  2. Compare against the schema expected by shared.ClientModelPackSchemaRoles and correct field names/types.
  3. Restore the file from git or back it up and let the CLI regenerate defaults.
  4. If upgrading from an older CLI version, migrate or delete the old-format settings file.

Example fix

// before: settings.json
{ "roles": { "planner": "gpt-4o", } }
// after: remove trailing comma
{ "roles": { "planner": "gpt-4o" } }
Defensive patterns

Strategy: validation

Validate before calling

data, err := os.ReadFile(settingsPath)
if err == nil {
    var v any
    if err := json.Unmarshal(data, &v); err != nil {
        return fmt.Errorf("settings file has invalid JSON: %w", err)
    }
}

Try / catch

if err != nil {
    if strings.Contains(err.Error(), "unmarshalling JSON file") {
        return fmt.Errorf("model settings file is malformed — validate with `jq . %s` or restore from git: %w", settingsPath, err)
    }
    return err
}

Prevention

When it happens

Trigger: json.Unmarshal on the settings file fails: malformed JSON, wrong schema (not a ClientModelPackSchemaRoles), truncated file from a partial write, or type mismatches (string where object expected).

Common situations: User hand-edited the model settings file and introduced a syntax error; an old CLI version wrote a schema the new version can't parse; the file was truncated by a crash or full disk mid-write.

Understand the failure class

Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.

Related errors


AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05). Data as JSON: /api/errors/3b27b4f0c8e0dd1d. Report an issue: GitHub.