cayleygraph/cayley · error

Unexpected type for @id %T

Error message

Unexpected type for @id %T

What it means

normalizeQuads in match.go:142 inspects a Match pattern's "@id" field to synthesize a single-entity quad when the pattern produces no quads of its own. If the "@id" value is not a Go string, this error is thrown (note: the message prints idString's type, which equals id's type). It indicates the pattern's @id was supplied as a non-string JSON value.

Source

Thrown at query/linkedql/steps/match.go:142

	patternClone := linkedql.GraphPattern{
		"@context": context,
	}
	for key, value := range pattern {
		patternClone[key] = value
	}
	return pattern
}

func quadsFromMap(o interface{}) ([]quad.Quad, error) {
	reader := jsonld.NewReaderFromMap(o)
	return quad.ReadAll(reader)
}

func normalizeQuads(quads []quad.Quad, pattern linkedql.GraphPattern) ([]quad.Quad, error) {
	if id, ok := pattern["@id"]; ok && len(quads) == 0 {
		idString, ok := id.(string)
		if !ok {
			return nil, fmt.Errorf("Unexpected type for @id %T", idString)
		}
		quads = append(quads, makeSingleEntityQuad(quad.IRI(idString)))
	}
	return quads, nil
}

func parsePattern(pattern linkedql.GraphPattern, ns *voc.Namespaces) ([]quad.Quad, error) {
	contextualizedPattern := contextualizePattern(pattern, ns)
	quads, err := quadsFromMap(contextualizedPattern)
	if err != nil {
		return nil, err
	}
	quads, err = normalizeQuads(quads, contextualizedPattern)
	if err != nil {
		return nil, err
	}
	if len(quads) == 0 && len(pattern) != 0 {
		return nil, fmt.Errorf("Pattern does not parse to any quad. `{}` is the only pattern allowed to not parse to any quad")

View on GitHub (pinned to 81dcd7d73e)

Solutions

  1. Set the pattern's @id to a plain string IRI.
  2. If @id comes from user JSON, coerce/validate it as string before constructing the GraphPattern.
  3. Check the %T in the message to identify which wrong type was supplied.

Example fix

// before
pattern := linkedql.GraphPattern{"@id": 42}
// after
pattern := linkedql.GraphPattern{"@id": "http://example.org/entity/42"}
Defensive patterns

Strategy: validation

Validate before calling

id, ok := pattern["@id"]
if ok {
  if _, isStr := id.(string); !isStr {
    return fmt.Errorf("@id must be a string, got %T", id)
  }
}

Type guard

func idString(pattern map[string]interface{}) (string, bool) {
  id, ok := pattern["@id"]
  if !ok { return "", false }
  s, ok := id.(string)
  return s, ok
}

Try / catch

quads, err := parsePattern(pattern, ctx)
if err != nil {
  if strings.Contains(err.Error(), "Unexpected type for @id") {
    // fix pattern construction: @id must be string
  }
  return err
}

Prevention

When it happens

Trigger: Building a linkedql Match / GraphPattern with "@id" set to a number, bool, map, or slice instead of a string, e.g. via unmarshalled JSON where @id was numeric.

Common situations: Programmatic pattern construction with the wrong Go type, or JSON queries where @id was written unquoted.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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