ory/hydra · error

jsonnetsecure: marshal

Error message

jsonnetsecure: marshal

What it means

`EvaluateAnonymousSnippet` marshals the processParameters struct (filename, snippet, ext/TLA vars) to JSON before sending it to a worker; if `json.Marshal` fails, this wrapped error is returned. This is nearly impossible with plain string fields and would indicate an unusable parameter value or a programming error.

Source

Thrown at oryx/jsonnetsecure/jsonnet_pool.go:259

		return "", ctx.Err()
	case output := <-w.stdout:
		return output, nil
	case err := <-w.stderr:
		return "", errors.New(err)
	}
}

func (vm *processPoolVM) EvaluateAnonymousSnippet(filename string, snippet string) (_ string, err error) {
	tracer := trace.SpanFromContext(vm.ctx).TracerProvider().Tracer("")
	ctx, span := tracer.Start(vm.ctx, "jsonnetsecure.processPoolVM.EvaluateAnonymousSnippet", trace.WithAttributes(attribute.String("filename", filename)))
	defer otelx.End(span, &err)

	params := vm.params
	params.Filename = filename
	params.Snippet = snippet
	pp, err := json.Marshal(params)
	if err != nil {
		return "", errors.Wrap(err, "jsonnetsecure: marshal")
	}

	ctx = context.WithValue(ctx, contextValuePath, vm.path)
	ctx = context.WithValue(ctx, contextValueArgs, vm.args)
	worker, err := vm.pool.puddle.Acquire(ctx)
	if err != nil {
		return "", errors.Wrap(err, "jsonnetsecure: acquire")
	}

	ctx, cancel := context.WithTimeoutCause(ctx, 1*time.Second, errors.Errorf("failed to run jsonnet within 1s: filename=%s", filename))
	defer cancel()
	result, err := worker.Value().eval(ctx, pp)
	if err != nil {
		worker.Destroy()
		return "", errors.Wrap(err, "jsonnetsecure: eval")
	} else {
		worker.Release()
	}

View on GitHub (pinned to 4174065ffb)

Solutions

  1. Inspect the wrapped cause (`errors.Cause(err)`) — it names the exact json unsupported-type error
  2. Audit recent changes to processParameters for fields that encoding/json cannot serialize; add json tags or remove them
  3. Log filename/snippet length to confirm which call site produced the bad params
  4. If using a forked/older version, upgrade to a release where params are JSON-safe

Example fix

// before: unserializable field added to params
type processParameters struct {
    Filename string `json:"filename"`
    Callback func() `json:"callback"` // unsupported
}
// after: keep params JSON-encodable (or exclude the field)
type processParameters struct {
    Filename string `json:"filename"`
    Callback func() `json:"-"` // never marshaled
}
Defensive patterns

Strategy: type-guard

Validate before calling

func paramsJSONSafe(params processParameters) error {
    _, err := json.Marshal(params)
    return err // run before relying on the VM
}

Type guard

func validSnippetParams(filename, snippet string) bool {
    return utf8.ValidString(filename) && utf8.ValidString(snippet)
}

Try / catch

pp, err := json.Marshal(params)
if err != nil {
    return "", fmt.Errorf("jsonnetsecure: marshal: %w — check processParameters for unsupported field types", err)
}

Prevention

When it happens

Trigger: Calling `EvaluateAnonymousSnippet` (directly or via the jsonnetsecure VM API) where `json.Marshal(params)` errors — practically only if params contains something json cannot encode; with current string-only fields this should never happen in normal use.

Common situations: Custom builds where processParameters gained a field with an unsupported type (chan, func, cyclic structure); extreme cases like invalid UTF-8 in strings generally still marshal (with replacement), so real occurrences point to code changes.

Understand the failure class

Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.

Related errors


AI-assisted analysis of ory/hydra@4174065ffb (2026-09-03). Data as JSON: /api/errors/d76cb993e2a8a417. Report an issue: GitHub.