# Sandcastle resumeSession Constraints: Validation Rules and File Requirements

> Explore Sandcastle resumeSession constraints. Learn about maxIterations validation rules and required file paths for uninterrupted Claude Code sessions.

- Repository: [Matt Pocock/sandcastle](https://github.com/mattpocock/sandcastle)
- Tags: best-practices
- Published: 2026-05-24

---

**The `resumeSession` feature in Sandcastle requires `maxIterations` to be set to `1` and mandates that the session JSONL file exists on the host filesystem at `~/.claude/projects/<encoded>/<id>.jsonl` before the agent can resume the Claude Code session.**

The `resumeSession` feature in mattpocock/sandcastle allows you to continue a previously saved Claude Code agent run inside a sandboxed environment. Before invoking this capability, the framework enforces specific constraints to ensure session integrity and prevent iteration conflicts.

## Validation Constraints for resumeSession

The `run` function in [`src/run.ts`](https://github.com/mattpocock/sandcastle/blob/main/src/run.ts) enforces two hard constraints before allowing a session to resume.

### maxIterations Must Equal 1

The resume logic only applies to the first iteration of the agent loop. In [`src/run.ts`](https://github.com/mattpocock/sandcastle/blob/main/src/run.ts) lines 52-58, the code validates that `maxIterations` is explicitly set to `1`. This constraint exists because the session restoration hook executes only at the beginning of the first iteration, and multi-iteration runs could lead to undefined behavior when combined with resumed state.

### Session File Must Exist on Host

The framework validates that the referenced session file exists on the host filesystem before attempting to transfer it to the sandbox. In [`src/run.ts`](https://github.com/mattpocock/sandcastle/blob/main/src/run.ts) lines 76-84, the code checks for the presence of the JSONL file at `~/.claude/projects/<encoded>/${resumeSession}.jsonl`. If the file is missing, the function throws an `Error` with a clear message before any sandbox operations begin.

## How Session Transfer Works

Once validation passes, Sandcastle coordinates the movement of session data between the host and the sandbox environment.

### Host and Sandbox Session Stores

In [`src/SessionStore.ts`](https://github.com/mattpocock/sandcastle/blob/main/src/SessionStore.ts), the `transferSession(from, to, id)` function (lines 20-70 and 119-136) handles the actual file movement. The implementation defines two concrete stores:

- **hostSessionStore**: Reads and writes JSONL files in `~/.claude/projects/<encoded>/` on the host machine
- **sandboxSessionStore**: Copies files through the bind-mount sandbox handle or via `docker cp`/`podman cp` for isolated environments

### Orchestrator Execution

In [`src/Orchestrator.ts`](https://github.com/mattpocock/sandcastle/blob/main/src/Orchestrator.ts) lines 79-99, the per-iteration loop constructs both stores and invokes `transferSession` when `i === 1` and a `resumeSession` ID is present. This copies the JSONL file into the sandbox's `~/.claude/projects/<encoded>/` directory before the agent starts.

## CLI Flag Injection

After transferring the session file, Sandcastle must instruct Claude Code to load it. In [`src/AgentProvider.ts`](https://github.com/mattpocock/sandcastle/blob/main/src/AgentProvider.ts) lines 70-74, the `buildPrintCommand` method appends the `--resume <id>` flag to the CLI command. This instructs the agent to restore its internal conversation state, tool call history, and token usage from the supplied JSONL file.

## Error Handling

The feature implements specific error handling for constraint violations:

- **Missing file**: If the session file does not exist during validation, [`src/run.ts`](https://github.com/mattpocock/sandcastle/blob/main/src/run.ts) throws a standard `Error` (lines 77-84)
- **Transfer failure**: If the file copy fails due to permissions or network issues, the Orchestrator wraps the error in a `SessionCaptureError` (lines 92-98 in [`src/Orchestrator.ts`](https://github.com/mattpocock/sandcastle/blob/main/src/Orchestrator.ts))

## Usage Example

```typescript
import { run } from "./src/run.js";
import { claudeCode } from "./src/AgentProvider.js";
import { docker } from "./src/SandboxFactory.js";

await run({
  agent: claudeCode("claude-opus-4-7"),
  sandbox: docker({ imageName: "sandcastle:myrepo" }),
  cwd: "/my/project",
  prompt: "Continue the previous analysis from where we left off",
  resumeSession: "abc-123", // File must exist at ~/.claude/projects/<encoded>/abc-123.jsonl
  maxIterations: 1,          // Required constraint
});

```

Running this script validates the constraints, transfers the session file into the sandbox, and launches `claude --resume abc-123` to continue the previous conversation exactly where it paused.

## Summary

- **Set `maxIterations: 1`** when using `resumeSession` to satisfy the validation logic in [`src/run.ts`](https://github.com/mattpocock/sandcastle/blob/main/src/run.ts)
- **Verify file existence** at `~/.claude/projects/<encoded>/<id>.jsonl` before running, or the framework throws an error
- **Transfer mechanism** uses `SessionStore.transferSession` called by the Orchestrator at the first iteration only
- **CLI integration** occurs via [`AgentProvider.ts`](https://github.com/mattpocock/sandcastle/blob/main/AgentProvider.ts) which appends the `--resume <id>` flag to the Claude Code command
- **Error types** include standard `Error` for missing files and `SessionCaptureError` for failed transfers

## Frequently Asked Questions

### What happens if I set maxIterations greater than 1 with resumeSession?

The validation logic in [`src/run.ts`](https://github.com/mattpocock/sandcastle/blob/main/src/run.ts) lines 52-58 will throw an error preventing execution. The resume hook is designed to run only once at the start of the first iteration, making multi-iteration resumes architecturally incompatible with the current implementation.

### Where does Sandcastle look for the session file?

According to the source code in [`src/run.ts`](https://github.com/mattpocock/sandcastle/blob/main/src/run.ts) lines 76-84, Sandcastle expects the file at `~/.claude/projects/<encoded>/${resumeSession}.jsonl` on the host filesystem, where `<encoded>` represents the encoded project path. The file must exist before the `run` function executes.

### Can I resume a session in an isolated sandbox without bind mounts?

Yes. While bind-mount providers allow direct file access, isolated sandboxes use the `sandboxSessionStore` implementation which transfers files via `docker cp` or `podman cp` mechanisms. The `transferSession` abstraction in [`src/SessionStore.ts`](https://github.com/mattpocock/sandcastle/blob/main/src/SessionStore.ts) handles both transparently.

### What error occurs if the session file is missing?

If the JSONL file does not exist at the expected path, [`src/run.ts`](https://github.com/mattpocock/sandcastle/blob/main/src/run.ts) throws an `Error` with a descriptive message explaining that the session file could not be found. This validation occurs before any sandbox container operations, preventing wasted resources on failed runs.