gravitational/teleport · error

error writing merged JSON: %w

Error message

error writing merged JSON: %w

What it means

After successfully merging the two decoded JSON values, JSONMerge re-serializes the result with json.Marshal and wraps any failure. Because the merged value is built from already-decoded JSON, this is rare — it mainly guards against internal invariants (e.g. unsupported values introduced by custom mergeJSON behavior such as NaN-like or channel-bearing values).

Source

Thrown at lib/accessgraph/apiclient/jsonmerge/jsonmerge.go:50

		data = []byte(`{}`)
	}
	if patch == nil {
		patch = []byte(`{}`)
	}

	var dataValue any
	if err := unmarshalJSON(data, &dataValue); err != nil {
		return nil, fmt.Errorf("error in data JSON: %w", err)
	}

	var patchValue any
	if err := unmarshalJSON(patch, &patchValue); err != nil {
		return nil, fmt.Errorf("error in patch JSON: %w", err)
	}

	merged, err := json.Marshal(mergeJSON(dataValue, patchValue))
	if err != nil {
		return nil, fmt.Errorf("error writing merged JSON: %w", err)
	}
	return merged, nil
}

func unmarshalJSON(data []byte, value any) error {
	decoder := json.NewDecoder(bytes.NewReader(data))
	decoder.UseNumber()
	return decoder.Decode(value)
}

func mergeJSON(data, patch any) any {
	patchObject, ok := patch.(map[string]any)
	if !ok {
		return data
	}

	switch dataObject := data.(type) {
	case map[string]any:

View on GitHub (pinned to 1283425b60)

Solutions

  1. Inspect the wrapped marshal error message for the offending Go type/value.
  2. Check recent changes to mergeJSON in lib/accessgraph/apiclient/jsonmerge for non-JSON-safe values.
  3. Ensure both inputs are plain JSON documents (objects/arrays/scalars); report a bug if inputs are plainly valid.
Defensive patterns

Strategy: try-catch

Validate before calling

// Inputs can be validated; marshal failure is internal — ensure inputs are plain JSON:
if !json.Valid(data) || !json.Valid(patch) { return nil, errors.New("inputs must be valid JSON") }

Try / catch

merged, err := jsonmerge.JSONMerge(data, patch)
if err != nil {
	if strings.Contains(err.Error(), "error writing merged JSON") {
		// likely a jsonmerge internals bug: log inputs and file an issue
	}
}

Prevention

When it happens

Trigger: json.Marshal of the mergeJSON(dataValue, patchValue) result fails — practically only if mergeJSON inserts a value json.Marshal cannot represent (channels, funcs, cyclic structures) rather than plain decoded JSON.

Common situations: A code change to mergeJSON that introduces non-marshalable sentinel values; custom unmarshalJSON hooks producing exotic types; otherwise this indicates a library bug rather than caller input.

Understand the failure class

Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.

Related errors


AI-assisted analysis of gravitational/teleport@1283425b60 (2026-09-02). Data as JSON: /api/errors/09265092b8aab129. Report an issue: GitHub.