SigNoz/signoz · error

invalid value for key %s: %v

Error message

invalid value for key %s: %v

What it means

buildTracesFilterQuery (v3 traces builder) failed to validate/cast a filter value against the key's DataType via utils.ValidateAndCastValue. The message names the key and nests the underlying cast error, meaning the value's type does not match the declared attribute type.

Source

Thrown at pkg/query-service/app/traces/v3/query_builder.go:161

	}
	return int64(math.Pow(10, float64(19-count)))
}

func buildTracesFilterQuery(fs *v3.FilterSet) (string, error) {
	var conditions []string

	if fs != nil && len(fs.Items) != 0 {
		for _, item := range fs.Items {
			val := item.Value
			// generate the key
			columnName := getColumnName(item.Key)
			var fmtVal string
			item.Operator = v3.FilterOperator(strings.ToLower(strings.TrimSpace(string(item.Operator))))
			if item.Operator != v3.FilterOperatorExists && item.Operator != v3.FilterOperatorNotExists {
				var err error
				val, err = utils.ValidateAndCastValue(val, item.Key.DataType)
				if err != nil {
					return "", fmt.Errorf("invalid value for key %s: %v", item.Key.Key, err)
				}
			}
			if val != nil {
				fmtVal = utils.ClickHouseFormattedValue(val)
			}
			if operator, ok := tracesOperatorMappingV3[item.Operator]; ok {
				switch item.Operator {
				case v3.FilterOperatorContains, v3.FilterOperatorNotContains:
					val = utils.QuoteEscapedString(fmt.Sprintf("%v", item.Value))
					conditions = append(conditions, fmt.Sprintf("%s %s '%%%s%%'", columnName, operator, val))
				case v3.FilterOperatorRegex, v3.FilterOperatorNotRegex:
					conditions = append(conditions, fmt.Sprintf(operator, columnName, fmtVal))
				case v3.FilterOperatorExists, v3.FilterOperatorNotExists:
					if item.Key.IsColumn {
						subQuery, err := ExistsSubQueryForFixedColumn(item.Key, item.Operator)
						if err != nil {
							return "", err
						}

View on GitHub (pinned to 5069bf80b0)

Solutions

  1. Match the JSON value type to item.Key.DataType (numbers for int64/float64, bool for bool, string for string)
  2. Re-fetch attribute keys to get current DataTypes and rebuild the filter
  3. For exists/not-exists semantics, use those operators instead of supplying a dummy value

Example fix

// before
{"key":{"key":"duration_ns","dataType":"int64"},"value":"abc","operator":">"}

// after
{"key":{"key":"duration_ns","dataType":"int64"},"value":1000000,"operator":">"}
Defensive patterns

Strategy: validation

Validate before calling

if item.Operator != v3.FilterOperatorExists && item.Operator != v3.FilterOperatorNotExists {
    if _, err := utils.ValidateAndCastValue(item.Value, item.Key.DataType); err != nil {
        return fmt.Errorf("invalid value for %s", item.Key.Key)
    }
}

Type guard

func isCastsClean(v interface{}, dt v3.AttributeKeyDataType) bool {
    _, err := utils.ValidateAndCastValue(v, dt)
    return err == nil
}

Prevention

When it happens

Trigger: Sending a traces filter set where e.g. duration_ns (int64) receives "1.5s" or a string, or a bool key receives a non-boolean, with any operator other than exists/not exists.

Common situations: Hand-written API payloads with stringified numbers; stale filter sets saved before an attribute's dataType changed; frontend sending untyped input for numeric fields.

Related errors


AI-assisted analysis of SigNoz/signoz@5069bf80b0 (2026-08-28). Data as JSON: /api/errors/3a323ec8477cad80. Report an issue: GitHub.