Tencent/WeKnora · warning

sandbox session no longer exists

Error message

sandbox session no longer exists

What it means

ErrSandboxSessionDeleted is a sentinel error reporting that the durable WeKnora session owning a sandbox binding no longer exists. When the remote lifecycle manager detects the session was deleted, it cleans up the created sandbox/binding and returns this sentinel (often joined with cleanup errors via errors.Join) so callers never execute work with a nil handle.

Source

Thrown at internal/sandbox/session_lifecycle.go:30

	"github.com/Tencent/WeKnora/internal/types"
)

const (
	remoteMetadataTenantID       = "weknora_tenant_id"
	remoteMetadataSessionID      = "weknora_session_id"
	remoteMetadataBindingVersion = "weknora_binding_version"
	remoteMetadataProvider       = "weknora_provider"

	// remoteMetadataConfigID records which sandbox config created the sandbox.
	// Two configs in one workspace may share a provider account, so cleanup
	// must filter by config as well as tenant/session ownership.
	remoteMetadataConfigID = "weknora_sandbox_config_id"
)

// ErrSandboxSessionDeleted reports that the owning WeKnora session no longer
// exists. Callers must not execute work with the returned nil handle.
var ErrSandboxSessionDeleted = errors.New("sandbox session no longer exists")

// SessionExistenceChecker checks the tenant-scoped durable session record.
type SessionExistenceChecker interface {
	SessionExists(context.Context, SessionSandboxKey) (bool, error)
}

// remoteSessionLifecycle coordinates one provider's persistent sandboxes using
// an authoritative binding store. It contains no provider-native types.
type remoteSessionLifecycle struct {
	client          RemoteSandboxClient
	bindings        SessionSandboxBindingStore
	sessionChecker  SessionExistenceChecker
	createRequest   RemoteCreateRequest
	cleanupTimeout  time.Duration
	sandboxConfigID string
	now             func() time.Time
}

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Detect it with errors.Is(err, sandbox.ErrSandboxSessionDeleted) and skip/abandon the work unit gracefully instead of retrying.
  2. Purge queued tasks whose session was deleted; check session existence before enqueueing work.
  3. Treat it as an expected terminal state: log at info/warn, release the lifecycle lock, and drop cached bindings.

Example fix

// before
handle, err := lifecycle.BeginTurn(ctx, key)
if err != nil { return err } // retries forever on deleted sessions
// after
handle, err := lifecycle.BeginTurn(ctx, key)
if errors.Is(err, sandbox.ErrSandboxSessionDeleted) {
    return nil // session gone; drop the job
} else if err != nil { return err }
Defensive patterns

Strategy: try-catch

Validate before calling

exists, err := checker.SessionExists(ctx, key)
if err != nil { return err }
if !exists { return fmt.Errorf("session %s gone; skip", key.SessionID) }

Try / catch

handle, err := lifecycle.BeginTurn(ctx, key)
switch {
case errors.Is(err, sandbox.ErrSandboxSessionDeleted):
    log.Info("session deleted; dropping sandbox work")
    return nil
case err != nil:
    return err
}

Prevention

When it happens

Trigger: Resolving a binding or beginning a turn (resolveLocked/createAndBind path) when SessionExists reports false for the tenant/session key at internal/sandbox/session_lifecycle.go:161 or :375; the session was deleted concurrently or before sandbox creation finished.

Common situations: User deletes a session in another tab/API while a background job still runs work for it; stale queue messages referencing deleted sessions; race between session deletion and sandbox provisioning.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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