JuliusBrussee/caveman · error

envelope: encode scope

Error message

envelope: encode scope: %w

What it means

json.Marshal of the scope struct (version, organization_id, project_id, kind) failed while building the AAD for envelope encryption. This is essentially unreachable in practice — the struct contains only an int and three strings, which always marshal — so it exists purely to satisfy error handling in the fail-closed design.

Solutions

  1. Treat it as an internal invariant violation; the wrapped json error should be reported upstream
  2. If it ever reproduces, verify the Go toolchain/encoding/json version for anomalies
  3. No caller-side fix exists — the input struct is fixed by the library
  4. Retry after confirming non-degenerate Scope values is unnecessary; escalate as a bug
Defensive patterns

Strategy: try-catch

Try / catch

_, _, err := /* SealForScope/OpenForScope */
if err != nil && strings.Contains(err.Error(), "encode scope") {
    // internal invariant violation: report as a bug with the wrapped json error
}

Prevention

When it happens

Trigger: Calling SealForScope or OpenForScope when json.Marshal errors on the fixed scope struct; under current Go semantics this cannot occur for these field types, but the wrapped error would carry the json package's message.

Common situations: Not seen in practice; only a hypothetical broken encoding.Malformed or exotic Go runtime could theoretically trigger it.

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 JuliusBrussee/caveman@3ee70a1026 (2026-09-20). Data as JSON: /api/errors/b091a26dd75fcdc5. Report an issue: GitHub.

Appendix: source

Thrown at shared/platform/envelope/envelope.go:185

func scopeAAD(scope Scope) ([]byte, string, error) {
	scope.OrganizationID = strings.TrimSpace(scope.OrganizationID)
	scope.ProjectID = strings.TrimSpace(scope.ProjectID)
	scope.Kind = strings.TrimSpace(scope.Kind)
	if scope.OrganizationID == "" {
		return nil, "", fmt.Errorf("envelope: organization scope is required")
	}
	if scope.Kind == "" {
		return nil, "", fmt.Errorf("envelope: object kind is required")
	}
	aad, err := json.Marshal(struct {
		Version        int    `json:"version"`
		OrganizationID string `json:"organization_id"`
		ProjectID      string `json:"project_id"`
		Kind           string `json:"kind"`
	}{2, scope.OrganizationID, scope.ProjectID, scope.Kind})
	if err != nil {
		return nil, "", fmt.Errorf("envelope: encode scope: %w", err)
	}
	sum := sha256.Sum256(aad)
	return aad, hex.EncodeToString(sum[:]), nil
}

View on GitHub (pinned to 3ee70a1026)