Tencent/WeKnora · error

sandbox: no live sandbox for session %s

Error message

sandbox: no live sandbox for session %s

What it means

StatSessionFile stats a file in the session's live sandbox, but unlike the write paths it refuses to provision: if lookupSessionHandle reports no bound sandbox (ok == false), it returns the sentinel "sandbox: no live sandbox for session <id>". This means the session exists but currently has no running/registered remote sandbox.

Source

Thrown at internal/sandbox/session_manager.go:612

	return m.listFilesRecursive(ctx, handle, dir)
}

// StatSessionFile returns metadata for a single file without downloading
// contents. Returns an error when no sandbox is bound: callers of this
// method already hold a path from a prior ListSessionFiles call and should
// not race with reaper/destroy.
func (m *SessionBoundManager) StatSessionFile(
	ctx context.Context, sessionID, filePath string,
) (*RemoteStatEntry, error) {
	if strings.TrimSpace(filePath) == "" {
		return nil, errors.New("sandbox: path required for StatSessionFile")
	}
	handle, ok, err := m.lookupSessionHandle(ctx, sessionID)
	if err != nil {
		return nil, err
	}
	if !ok {
		return nil, fmt.Errorf("sandbox: no live sandbox for session %s", sessionID)
	}
	return m.client.Stat(ctx, handle, filePath)
}

// ReadSessionFile downloads a file from the session's live sandbox. Errors
// when no sandbox is bound for the same reason as StatSessionFile.
func (m *SessionBoundManager) ReadSessionFile(
	ctx context.Context, sessionID, filePath string,
) ([]byte, error) {
	if strings.TrimSpace(filePath) == "" {
		return nil, errors.New("sandbox: path required for ReadSessionFile")
	}
	handle, ok, err := m.lookupSessionHandle(ctx, sessionID)
	if err != nil {
		return nil, err
	}
	if !ok {
		return nil, fmt.Errorf("sandbox: no live sandbox for session %s", sessionID)

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Treat this as 'no file' if a missing sandbox means no staged files, and return a not-found result to the caller.
  2. Provision the sandbox first via a write path (e.g. WriteSessionInputFile) or resolveSession before statting.
  3. Check whether the session's sandbox TTL expired and re-provision.
  4. Verify the session ID is correct and still active in the binding store.

Example fix

// before
fi, err := mgr.StatSessionFile(ctx, sessionID, p)
// after
fi, err := mgr.StatSessionFile(ctx, sessionID, p)
if err != nil && strings.Contains(err.Error(), "no live sandbox for session") {
    return nil, os.ErrNotExist // no sandbox == no file
}
Defensive patterns

Strategy: type-guard

Validate before calling

// detect the no-live-sandbox sentinel before interpreting as a hard failure
func isNoLiveSandbox(err error) bool {
    return err != nil && strings.Contains(err.Error(), "no live sandbox for session")
}

Type guard

func isNoLiveSandboxErr(err error) bool {
    return err != nil && strings.Contains(err.Error(), "no live sandbox for session")
}

// usage
fi, err := mgr.StatSessionFile(ctx, sessionID, p)
switch {
case isNoLiveSandboxErr(err):
    return nil, os.ErrNotExist // no sandbox == file cannot exist
case err != nil:
    return nil, err
}

Try / catch

fi, err := mgr.StatSessionFile(ctx, sessionID, p)
if err != nil {
    if isNoLiveSandboxErr(err) {
        return nil, os.ErrNotExist
    }
    return nil, fmt.Errorf("stat %s: %w", p, err)
}

Prevention

When it happens

Trigger: Calling StatSessionFile for a session whose sandbox was never provisioned, already expired/reclaimed, or whose binding was cleaned up by the session lifecycle.

Common situations: Statting a file after sandbox TTL expiry, checking a session that never had a file staged, calling after idle cleanup, or using a stale session ID post-restart.

Related errors


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