ipfs/kubo · error

failed to unmarshal json. %s

Error message

failed to unmarshal json. %s

What it means

When `ipfs config <key> <value> --json` is given, Kubo parses the value string with encoding/json into an `any` before storing it. If the string is not valid JSON, the raw parse error is wrapped as 'failed to unmarshal json. %s' and the config is left unchanged.

Source

Thrown at core/commands/config.go:152

				id, err := nodePeerID(r)
				if err != nil {
					return err
				}
				got, err := peer.Decode(candidate)
				if err != nil || got != id {
					return errors.New("cannot set Identity.PeerID to a value that does not match the node's private key; use 'ipfs key rotate' to change the node identity")
				}
				output, err = setConfig(r, key, id.String())
				if err != nil {
					return err
				}
				return cmds.EmitOnce(res, output)
			}

			if parseJSON, _ := req.Options[configJSONOptionName].(bool); parseJSON {
				var jsonVal any
				if err := json.Unmarshal([]byte(value), &jsonVal); err != nil {
					err = fmt.Errorf("failed to unmarshal json. %s", err)
					return err
				}

				output, err = setConfig(r, key, jsonVal)
			} else if isbool, _ := req.Options[configBoolOptionName].(bool); isbool {
				output, err = setConfig(r, key, value == "true")
			} else {
				output, err = setConfig(r, key, value)
			}
		} else {
			// Check if user wants to expand auto values for getter
			expandAuto, _ := req.Options[configExpandAutoName].(bool)
			if expandAuto {
				output, err = getConfigWithAutoExpand(r, key)
			} else {
				output, err = getConfig(r, key)
			}
		}

View on GitHub (pinned to 329838acdf)

Solutions

  1. Validate the value first: `echo '<value>' | jq empty` and only then pass it to ipfs config --json
  2. Quote the value as a whole: ipfs config Addresses.API '"/ip4/127.0.0.1/tcp/5001"' --json
  3. If the value is a plain string/boolean, drop --json (or use --bool) and pass it raw
  4. Inspect the exact parse error after 'failed to unmarshal json.' — it names the byte offset and problem

Example fix

// before
$ ipfs config Datastore.StorageMax 10GB --json
failed to unmarshal json. invalid character '1'...
// after
$ ipfs config Datastore.StorageMax '"10GB"' --json
Defensive patterns

Strategy: validation

Validate before calling

echo "$value" | jq empty && ipfs config "$key" "$value" --json

Type guard

func validJSON(s string) bool { var v any; return json.Unmarshal([]byte(s), &v) == nil }

Try / catch

if err := run("ipfs", "config", key, val, "--json"); err != nil {
	if strings.Contains(err.Error(), "failed to unmarshal json") {
		// fall back: pass as plain string without --json
	}
}

Prevention

When it happens

Trigger: `ipfs config <key> <value> --json` where value is not valid JSON: single quotes (shell-stripped), unquoted bare words (`ipfs config Datastore.StorageMax 10GB --json`), unquoted keys, trailing commas, or shell-mangled quotes in a nested object.

Common situations: Shell quoting pitfalls: `--json '{"a":1}'` losing inner quotes, forgetting that bare strings must be JSON-quoted (`--json '"true"'`), scripts passing env vars that contain unescaped content; also users of the RPC `/api/v0/config` with the json flag.

Understand the failure class

Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.

Related errors


AI-assisted analysis of ipfs/kubo@329838acdf (2026-09-03). Data as JSON: /api/errors/dece020e782fc02a. Report an issue: GitHub.