cayleygraph/cayley · error

unexpected arguments: %v (%d)

Error message

unexpected arguments: %v (%d)

What it means

In GraphQL-to-gizmo query translation, the special keys limit/skip must carry exactly one value; iterateObject returns this error when a limit or skip field has zero or multiple values. It is a query-shape validation enforced during execution of the parsed has-constraints.

Source

Thrown at query/graphql/graphql.go:173

func iterateObject(ctx context.Context, qs graph.QuadStore, f *field, p *path.Path) (out []map[string]interface{}, _ error) {
	if len(f.Labels) != 0 {
		p = p.LabelContext(f.Labels)
	} else {
		p = p.LabelContext()
	}
	var (
		limit = -1
		skip  = 0
	)

	for _, h := range f.Has {
		switch h.Via {
		case quad.IRI(ValueKey): // special key - "id"
			p = p.Is(h.Values...)
		case quad.IRI(LimitKey), quad.IRI(SkipKey): // limit and skip
			if len(h.Values) != 1 {
				return nil, fmt.Errorf("unexpected arguments: %v (%d)", h.Values, len(h.Values))
			}
			n, ok := h.Values[0].(quad.Int)
			if !ok {
				return nil, fmt.Errorf("unexpected value type for %v: %T", string(h.Via), h.Values[0])
			}
			if h.Via == quad.IRI(LimitKey) {
				limit = int(n)
			} else {
				skip = int(n)
				if skip < 0 {
					skip = 0
				}
			}
		default: // everything else - Has constraint
			if len(h.Labels) != 0 {
				p = p.LabelContext(h.Labels)
			}
			if h.Rev {

View on GitHub (pinned to 81dcd7d73e)

Solutions

  1. Ensure the query specifies limit (or skip) exactly once with a single integer value.
  2. Deduplicate the generated Has constraints if you build them programmatically.
  3. Validate the GraphQL document before execution so repeated limit/skip fields are rejected upstream.

Example fix

// before (generated has constraints)
{Via: LimitKey, Values: []interface{}{quad.Int(10), quad.Int(20)}}
// after
{Via: LimitKey, Values: []interface{}{quad.Int(10)}}
Defensive patterns

Strategy: validation

Validate before calling

for (const h of has) { if ((h.Via === 'limit' || h.Via === 'skip') && h.Values.length !== 1) { throw new Error(h.Via + ' must have exactly one value'); } }

Type guard

function isValidLimitConstraint(h) { return h.Values.length === 1; }

Try / catch

out, err := iterateObject(ctx, qs, field, p)
if err != nil && strings.Contains(err.Error(), "unexpected arguments") { /* dedupe limit/skip constraints */ }

Prevention

When it happens

Trigger: A GraphQL query where a @limit/@skip-style directive or field (quad.IRI(LimitKey)/SkipKey) resolves to h.Values with length != 1 — e.g. duplicating the limit key or supplying an array of values.

Common situations: Query builders that append limit values twice, or hand-crafted has-argument lists in tests/tools bypassing GraphQL schema validation.

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/f4e50bb71b18033f. Report an issue: GitHub.