kubernetes/kops · error

unhandled token type %T

Error message

unhandled token type %T

What it means

WriteToken handles Go types corresponding to JSON values: bool, string, float64, json.Number, json.Delim, and nil. Passing any other Go type (int, map[string]any, struct, time.Time, etc.) fails with this error because the writer only re-emits tokens produced by a json.Decoder, not arbitrary values.

Source

Thrown at pkg/jsonutils/streamwriter.go:148

		//	string, for JSON string literals
	case string:
		v = "\"" + tt + "\""

		//	float64, for JSON numbers
	case float64:
		v = fmt.Sprintf("%g", tt)

		//	Number, for JSON numbers
	case json.Number:
		v = tt.String()

		//	nil, for JSON null
	case nil:
		v = "null"

	default:
		return fmt.Errorf("unhandled token type %T", tt)
	}

	switch state {
	case '{':
		j.state += "F"
		j.path = append(j.path, fmt.Sprintf("%s", token))
		return j.writeRaw(j.indent + v + ": ")
	case '[':
		if err := j.writeRaw(j.indent + v); err != nil {
			return err
		}
		j.deferred = ",\n"
		return nil
	case 'F':
		j.state = j.state[:len(j.state)-1]
		j.path = j.path[:len(j.path)-1]
		if err := j.writeRaw(v); err != nil {
			return err

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Convert the value to a supported token type first: use json.Number(strconv.FormatInt(n, 10)) for integers.
  2. Only feed tokens from json.Decoder.Token() into WriteToken.
  3. For non-token values, marshal to JSON first and re-decode with UseNumber, then stream the tokens.

Example fix

// before
w.WriteToken(count) // count is int
// after
w.WriteToken(json.Number(strconv.Itoa(count)))
Defensive patterns

Strategy: type-guard

Validate before calling

func isJSONToken(v any) bool {
	switch v.(type) {
	case nil, bool, string, float64, json.Number, json.Delim:
		return true
	}
	return false
}

Type guard

func isJSONToken(v any) bool {
	switch v.(type) {
	case nil, bool, string, float64, json.Number, json.Delim:
		return true
	}
	return false
}

Prevention

When it happens

Trigger: Calling WriteToken(v) directly with a raw Go value such as an int, int64, []string, or struct instead of a json.Token from Decoder.Token(); e.g. w.WriteToken(42) — note json.Decoder yields float64 or json.Number, never int.

Common situations: Mixing encoding/json marshalling with token streaming; assuming numbers arrive as int; feeding decoded map values straight into the writer.

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/5130921f91c1887d. Report an issue: GitHub.