Tencent/WeKnora · error

remote provider returned sandbox %q outside metadata filter

Error message

remote provider returned sandbox %q outside metadata filter

What it means

This is a defense-in-depth check: after listing sandboxes by metadata filter, each returned summary's metadata is re-verified locally with metadataMatches. If the provider returns a sandbox whose metadata does not match the requested filter, the library treats it as a provider contract violation and fails rather than connecting to (or cleaning up) a sandbox it does not own.

Source

Thrown at internal/sandbox/session_lifecycle.go:303

		left, right := summaries[i], summaries[j]
		if left.StartedAt.Equal(right.StartedAt) {
			return left.ID < right.ID
		}
		if left.StartedAt.IsZero() {
			return false
		}
		if right.StartedAt.IsZero() {
			return true
		}
		return left.StartedAt.Before(right.StartedAt)
	})

	for _, summary := range summaries {
		if summary.ID == "" || summary.State == RemoteStateTerminal {
			continue
		}
		if !metadataMatches(summary.Metadata, metadata) {
			return nil, false, fmt.Errorf(
				"remote provider returned sandbox %q outside metadata filter",
				summary.ID,
			)
		}
		handle, err := l.client.Connect(ctx, summary.ID)
		if err != nil {
			if CanReplaceRemoteBinding(err) {
				continue
			}
			return nil, false, fmt.Errorf("connect owned remote sandbox: %w", err)
		}
		if err := l.validateHandle(handle, summary.ID); err != nil {
			return nil, false, err
		}
		if err := l.cleanupOwnedDuplicates(ctx, summaries, summary.ID, metadata); err != nil {
			return nil, false, err
		}
		templateID := summary.TemplateID

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Compare the returned sandbox's metadata against your filter to find the mismatch (case, encoding, extra/missing keys)
  2. Normalize metadata values at creation time (lowercase, no special characters) so provider and local matching agree
  3. Report/work around the provider's filter semantics — e.g. post-filter locally and skip non-matching IDs instead of erroring, if you control the client
  4. Verify no other workload is creating sandboxes with colliding metadata keys

Example fix

// before
metadata := map[string]string{"owner": userEmail} // case varies across services
// after
metadata := map[string]string{"owner": strings.ToLower(userEmail)} // stable, exact-match safe
Defensive patterns

Strategy: validation

Validate before calling

// ensure metadata written at creation matches what filtering expects
md := map[string]string{"session": key, "owner": strings.ToLower(owner)}
if !sandbox.MetadataMatches(md, sandbox.MetadataFor(key)) {
    return errors.New("metadata would not match recovery filter")
}

Type guard

func ownedBySession(summary sandbox.RemoteSandboxSummary, md map[string]string) bool {
    return sandbox.MetadataMatches(summary.Metadata, md)
}

Try / catch

handle, err := session.Resolve(ctx, key)
if err != nil && strings.Contains(err.Error(), "outside metadata filter") {
    // provider returned unfiltered results: normalize metadata and re-resolve
    handle, err = session.Resolve(ctx, key)
}

Prevention

When it happens

Trigger: During recoverOwnedSandbox, a non-terminal summary from client.List has metadata that fails metadataMatches(summary.Metadata, metadata) — i.e. the provider ignored or loosened the metadata filter, or metadata keys/values were altered after creation.

Common situations: Providers that match metadata partially or case-insensitively while the local check is exact; provider stripping or re-encoding metadata values; sandboxes created by another tenant/session sharing a prefix of the metadata; provider SDK bug returning unfiltered pages.

Related errors


AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02). Data as JSON: /api/errors/70d9376facbef4fb. Report an issue: GitHub.