Tencent/WeKnora · error

sandbox: create workspace directory

Error message

sandbox: create workspace directory: %w

What it means

WriteSessionWorkspaceFile (for model-authored files) calls MakeDir on the parent of the cleaned target path after ensuring standard workspace dirs; failure is wrapped as "sandbox: create workspace directory". The workspace dirs under SessionOutputRoot are best-effort (errors ignored), so this error means the specific parent directory of the target file could not be created.

Solutions

  1. Inspect the wrapped error to identify permission vs. path problems.
  2. Sanitize/validate model-authored paths before writing (clean, restrict to workspace root).
  3. Verify the sandbox is alive; re-resolve the session and retry.
  4. Check provider disk quotas.

Example fix

// before
p := modelOutput.Name() // may contain spaces/odd chars
err := mgr.WriteSessionWorkspaceFile(ctx, sessionID, p, data)
// after
p := path.Join("/workspace", path.Clean(sanitizeName(modelOutput.Name())))
err := mgr.WriteSessionWorkspaceFile(ctx, sessionID, p, data)
Defensive patterns

Strategy: validation

Validate before calling

// sanitize model-authored paths before writing
func sanitizeWorkspacePath(name string) string {
    name = path.Clean("/" + name) // anchor to root, drop ..
    name = strings.Map(func(r rune) rune {
        if unicode.IsLetter(r) || unicode.IsDigit(r) || r == '.' || r == '-' || r == '_' || r == '/' {
            return r
        }
        return '_'
    }, name)
    return path.Join("/workspace", name)
}

Try / catch

if err := mgr.WriteSessionWorkspaceFile(ctx, sessionID, p, data); err != nil {
    if strings.Contains(err.Error(), "create workspace directory") {
        return fmt.Errorf("workspace path %q rejected by sandbox: %w", p, err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling WriteSessionWorkspaceFile when MakeDir(path.Dir(clean)) fails — permission denied, invalid nested path, sandbox terminated mid-call, or provider API error.

Common situations: Model-generated paths containing illegal characters or escaping the workspace root, sandbox image with read-only workspace, quota exceeded, or a stale sandbox handle after expiry.

Related errors


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

Appendix: source

Thrown at internal/sandbox/session_manager.go:551

	ctx context.Context, sessionID, filePath string, content []byte,
) error {
	if err := m.requireRemoteBackend(); err != nil {
		return err
	}
	if strings.TrimSpace(sessionID) == "" {
		return errors.New("sandbox: session ID required for workspace write")
	}
	clean, err := cleanSessionWorkspaceWritePath(filePath)
	if err != nil {
		return err
	}
	handle, err := m.resolveSession(ctx, sessionID)
	if err != nil {
		return err
	}
	m.ensureSessionWorkspaceDirs(ctx, handle, SessionOutputRoot)
	if err := ignoreExistingDir(m.client.MakeDir(ctx, handle, path.Dir(clean))); err != nil {
		return fmt.Errorf("sandbox: create workspace directory: %w", err)
	}
	if err := m.client.WriteFile(ctx, handle, clean, content); err != nil {
		return fmt.Errorf("sandbox: write session file %s: %w", clean, err)
	}
	return nil
}

// RemoveSessionInputPath deletes a staged attachment. It is a no-op when the
// session has no live sandbox and never provisions one.
func (m *SessionBoundManager) RemoveSessionInputPath(
	ctx context.Context, sessionID, targetPath string,
) error {
	if err := m.requireRemoteBackend(); err != nil {
		return err
	}
	clean, err := cleanSessionInputPath(targetPath)
	if err != nil {
		return err

View on GitHub (pinned to 988cbb0330)