plandex-ai/plandex · error

invalid json: %w

Error message

invalid json: %w

What it means

validateJSON first does a preliminary json.Unmarshal into interface{} to strip meta-keywords like top-level $schema. This error means the supplied JSON bytes are syntactically invalid JSON before schema validation can even run.

Source

Thrown at app/cli/schema/schemas.go:50

	source string
	fs     embed.FS
}

func ValidateModelsInputJSON(jsonData []byte) (shared.ClientModelsInput, error) {
	return validateJSON[shared.ClientModelsInput](jsonData, SchemaPathInputConfig)
}

func ValidateModelPackInlineJSON(jsonData []byte) (shared.ClientModelPackSchemaRoles, error) {
	return validateJSON[shared.ClientModelPackSchemaRoles](jsonData, SchemaPathModelPackInline)
}

func validateJSON[T any](jsonData []byte, schemaPath SchemaPath) (T, error) {
	var zero T

	// strip meta-keywords that break additionalProperties ──
	var tmp interface{}
	if err := json.Unmarshal(jsonData, &tmp); err != nil {
		return zero, fmt.Errorf("invalid json: %w", err)
	}
	if obj, ok := tmp.(map[string]interface{}); ok {
		delete(obj, "$schema") // ignore top-level $schema
		var err error
		jsonData, err = json.Marshal(obj)
		if err != nil {
			return zero, fmt.Errorf("error marshalling json: %w", err)
		}
	}

	schemaLoader := newEmbeddedSchemaLoader(schemaPath)
	documentLoader := gojsonschema.NewBytesLoader(jsonData)

	result, err := gojsonschema.Validate(schemaLoader, documentLoader)
	if err != nil {
		return zero, err
	}
	if !result.Valid() {

View on GitHub (pinned to e2d772072e)

Solutions

  1. Validate the JSON with a linter/parser (jq . file.json) and fix the syntax error
  2. Strip markdown code fences and surrounding prose before passing bytes in
  3. Ensure the file is UTF-8 and not truncated/empty
  4. Regenerate or re-export the JSON from its source

Example fix

// before
modelsJson := []byte("{\"model\": \"gpt-4\",}") // trailing comma
// after
modelsJson := []byte("{\"model\": \"gpt-4\"}")
Defensive patterns

Strategy: validation

Validate before calling

func isProbablyJSON(b []byte) error {
    trimmed := bytes.TrimSpace(bytes.TrimPrefix(bytes.TrimSpace(b), []byte("```json")))
    trimmed = bytes.TrimSuffix(trimmed, []byte("```"))
    var v interface{}
    return json.Unmarshal(trimmed, &v)
}

Type guard

func isJSONObject(b []byte) bool {
    var m map[string]interface{}
    return json.Unmarshal(b, &m) == nil
}

Try / catch

err := ValidateModelsInputJSON(data)
if err != nil && strings.HasPrefix(err.Error(), "invalid json:") {
    // surface syntax error with byte offset from wrapped json.SyntaxError
    var se *json.SyntaxError
    if errors.As(err, &se) {
        log.Printf("JSON syntax error at offset %d", se.Offset)
    }
}

Prevention

When it happens

Trigger: ValidateModelsInputJSON or ValidateModelPackInlineJSON is called with bytes that fail json.Unmarshal: trailing commas, comments, single quotes, truncated output, or non-JSON text (e.g. an LLM wrapped JSON in markdown fences).

Common situations: Feeding model settings from a hand-edited file with a syntax error; passing LLM-generated JSON that includes ```json fences or trailing text; empty string input.

Understand the failure class

Related errors


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