projectdiscovery/nuclei · error

object can be a key:value or a string

Error message

object can be a key:value or a string

What it means

SliceOrMapSlice (pkg/fuzz/type.go) backs the `fuzz:` payload field of fuzzing rules and accepts exactly two shapes: a flat array of strings or an object of string->string. UnmarshalJSON tries the array first, then the ordered map; if both fail (the JSON is a scalar, a nested array, an array of non-strings, or an object with non-string values), it returns this error and template/JSON parsing of the fuzz rule aborts.

Source

Thrown at pkg/fuzz/type.go:80

				},
				{
					Type: "object",
				},
			},
		},
	}
	return gotType
}

// UnmarshalJSON implements json.Unmarshaler interface.
func (v *SliceOrMapSlice) UnmarshalJSON(data []byte) error {
	// try to unmashal as a string and fallback to map
	if err := json.Unmarshal(data, &v.Value); err == nil {
		return nil
	}
	err := json.Unmarshal(data, &v.KV)
	if err != nil {
		return fmt.Errorf("object can be a key:value or a string")
	}
	return nil
}

// MarshalJSON implements json.Marshaler interface.
func (v SliceOrMapSlice) MarshalJSON() ([]byte, error) {
	if v.KV != nil {
		return json.Marshal(v.KV)
	}
	return json.Marshal(v.Value)
}

// UnmarshalYAML implements yaml.Unmarshaler interface.
func (v *SliceOrMapSlice) UnmarshalYAML(callback func(interface{}) error) error {
	// try to unmarshal it as a string and fallback to map
	if err := callback(&v.Value); err == nil {
		return nil
	}

View on GitHub (pinned to 265b3a3dec)

Solutions

  1. Use a flat array of quoted strings: "fuzz": ["'", "admin"]
  2. Or an object where every key and value is a string: "fuzz": {"user": "admin"}
  3. Quote numeric and boolean payloads so they marshal as JSON strings
  4. Validate the template with `nuclei -validate` before running it

Example fix

// before
"fuzz": {
  "user": 123,
  "nested": { "a": "b" }
}

// after
"fuzz": {
  "user": "123"
}
Defensive patterns

Strategy: type-guard

Validate before calling

var raw any
if err := json.Unmarshal(data, &raw); err != nil {
    return err
}
switch v := raw.(type) {
case []any:
    for _, it := range v {
        if _, ok := it.(string); !ok {
            return fmt.Errorf("fuzz payload array must contain only strings")
        }
    }
case map[string]any:
    for _, val := range v {
        if _, ok := val.(string); !ok {
            return fmt.Errorf("fuzz payload values must be strings")
        }
    }
default:
    return fmt.Errorf("fuzz must be an array of strings or a string-to-string object")
}

Type guard

func isSliceOrMapSliceJSON(data []byte) bool {
    var arr []string
    if json.Unmarshal(data, &arr) == nil {
        return true
    }
    var m map[string]string
    return json.Unmarshal(data, &m) == nil
}

Try / catch

if err := json.Unmarshal(data, &v); err != nil {
    if strings.Contains(err.Error(), "object can be a key:value or a string") {
        return fmt.Errorf("invalid fuzz payload shape in %s: use [\"str\",...] or {\"k\":\"v\"}", path)
    }
    return err
}

Prevention

When it happens

Trigger: Supplying `"fuzz": 123` or `"fuzz": true` in JSON; an array with nested arrays or numbers like [["a"]] or [1,2]; an object whose values are objects, arrays, or unquoted numbers; programmatically marshaling a struct into the fuzz field and hitting a shape mismatch.

Common situations: Hand-writing fuzz rules in JSON tools or UIs that infer types (numbers, booleans) instead of strings; pipelines that generate templates from typed data and forget to stringify payloads; porting YAML templates to JSON and keeping YAML-style nested structures.

Related errors


AI-assisted analysis of projectdiscovery/nuclei@265b3a3dec (2026-08-15). Data as JSON: /api/errors/1688b2aff11b1564. Report an issue: GitHub.