cayleygraph/cayley · error

multiple fields at location root %s

Error message

multiple fields at location root %s

What it means

In mql/build_iterator.go:84, buildShape handles a JSON array in the MQL query. An array at the root represents alternative field shapes; more than one element means multiple fields were specified at the same root location, which MQL does not support, so this error is thrown with the path's display string. A single-element array or empty array (match-all) are the only allowed forms.

Source

Thrown at query/mql/build_iterator.go:84

		if math.Floor(t) == t {
			// Treat it like an integer.
			s = shape.Lookup{quad.Int(t)}
		} else {
			s = shape.Lookup{quad.Float(t)}
		}
	case string:
		// for JSON strings
		s = buildFixed(t)
	case []interface{}:
		// for JSON arrays
		q.isRepeated[path] = true
		if len(t) == 0 {
			s = buildAllResult(path)
			optional = true
		} else if len(t) == 1 {
			s, optional, err = q.buildShape(t[0], path)
		} else {
			err = fmt.Errorf("multiple fields at location root %s", path.DisplayString())
		}
	case map[string]interface{}:
		// for JSON objects
		s, err = q.buildShapeMap(t, path)
	case nil:
		s = buildAllResult(path)
		optional = true
	default:
		err = fmt.Errorf("Unknown JSON type: %T", query)
	}
	if err != nil {
		return nil, false, err
	}
	s = shape.Save{
		From: s,
		Tags: []string{string(path)},
	}
	return s, optional, nil

View on GitHub (pinned to 81dcd7d73e)

Solutions

  1. Reduce the array at that location to a single field object.
  2. Merge the multiple field definitions into one map if they should apply together.
  3. Use separate queries if the alternatives are mutually exclusive.
  4. Check the path string in the message to locate the offending query position.

Example fix

// before
query := []interface{}{map[string]interface{}{"name": nil}, map[string]interface{}{"age": nil}}
// after
query := map[string]interface{}{"name": nil, "age": nil}
Defensive patterns

Strategy: validation

Validate before calling

func validateMQLArrayAtMostOne(v interface{}) error {
  arr, ok := v.([]interface{})
  if !ok || len(arr) <= 1 { return nil }
  return fmt.Errorf("MQL arrays may contain at most one field spec, got %d", len(arr))
}

Type guard

func isSingleSpecArray(v interface{}) bool {
  a, ok := v.([]interface{})
  return ok && len(a) <= 1
}

Try / catch

it, err := mql.BuildIteratorTree(query)
if err != nil {
  if strings.Contains(err.Error(), "multiple fields at location root") {
    return fmt.Errorf("merge multiple field objects into one in query")
  }
  return err
}

Prevention

When it happens

Trigger: Executing a MQL query (mql.BuildIteratorTree) where a JSON array value contains two or more field definitions at the same location, e.g. [[{...},{...}]] style multiple alternatives.

Common situations: Hand-writing MQL queries that mix multiple top-level field sets, or programmatic query generation emitting an array with multiple query maps.

Understand the failure class

Background: "Invalid query parameter" / "Failed to parse value of ...": fixing bad query string parameters across APIs — this error's family across 36 libraries.

Related errors


AI-assisted analysis of cayleygraph/cayley@81dcd7d73e (2026-09-06). Data as JSON: /api/errors/641dd205af609b7c. Report an issue: GitHub.