thanos-io/thanos · error

unknown targetHealth

Error message

unknown targetHealth: %v

What it means

TargetHealth.UnmarshalJSON looks up the unquoted, upper-cased string in TargetHealth_value (the protobuf-generated enum value map). If the string is not a known state, this error reports the unknown raw JSON entry.

Solutions

  1. Use exactly one of the supported values: "unknown", "healthy", "unhealthy" (case-insensitive).
  2. Trim whitespace and control characters from the input before unmarshaling.
  3. Align versions between producer and consumer so both share the same TargetHealth enum set.
  4. Map foreign health vocabularies to TargetHealth values in a preprocessing step.

Example fix

// before
{"health": "up"}
// after
{"health": "healthy"}
Defensive patterns

Strategy: validation

Validate before calling

const valid = ['unknown','healthy','unhealthy'];
if (!valid.includes(health.trim().toLowerCase())) throw new Error('unknown targetHealth: '+health);

Type guard

func isTargetHealth(s string) bool {
    _, ok := targetspb.TargetHealth_value[strings.ToUpper(strings.TrimSpace(s))]
    return ok
}

Try / catch

if err := json.Unmarshal(raw, &h); err != nil {
    log.Warn("bad targetHealth, defaulting to unknown")
    h = targetspb.TargetHealth_UNKNOWN
}

Prevention

When it happens

Trigger: UnmarshalJSON is given a quoted string whose value is not unknown/healthy/unhealthy (case-insensitive), e.g. "health": "Healthy " with whitespace, or a foreign value like "UP".

Common situations: Producers using different enum vocabularies (e.g. Prometheus health strings in another format); typos or trailing whitespace; version skew adding new enum values unknown to the older decoder.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07). Data as JSON: /api/errors/c3c4446f92ff332e. Report an issue: GitHub.

Appendix: source

Thrown at pkg/targets/targetspb/custom.go:44

		Result: &TargetsResponse_Warning{
			Warning: warning.Error(),
		},
	}
}

func (x *TargetHealth) UnmarshalJSON(entry []byte) error {
	fieldStr, err := strconv.Unquote(string(entry))
	if err != nil {
		return errors.Wrapf(err, "targetHealth: unquote %v", string(entry))
	}

	if fieldStr == "" {
		return errors.New("empty targetHealth")
	}

	state, ok := TargetHealth_value[strings.ToUpper(fieldStr)]
	if !ok {
		return errors.Errorf("unknown targetHealth: %v", string(entry))
	}
	*x = TargetHealth(state)
	return nil
}

func (x *TargetHealth) MarshalJSON() ([]byte, error) {
	return []byte(strconv.Quote(strings.ToLower(x.String()))), nil
}

func (x TargetHealth) Compare(y TargetHealth) int {
	return int(x) - int(y)
}

func (t1 *ActiveTarget) Compare(t2 *ActiveTarget) int {
	if d := strings.Compare(t1.ScrapeUrl, t2.ScrapeUrl); d != 0 {
		return d
	}

View on GitHub (pinned to 35b8b99117)