earendil-works/pi · error · HarnessNotImplemented
AgentHarness.create.restore is not implemented yet
Error message
AgentHarness.create.restore is not implemented yet
What it means
AgentHarness.create() builds a harness over a SessionTree, but restoring an existing session is not implemented yet: if options.session.findRecords({ limit: 1 }) returns any record, create rejects with HarnessNotImplemented('create.restore') instead of resuming. The harness is a work-in-progress surface where most operations similarly reject with HarnessNotImplemented, so create only succeeds on a fresh, empty session. The error class carries an `operation` field ('create.restore') for precise handling.
Source
Thrown at packages/agent/src/harness/agent-harness.ts:351
skills: options.resources?.skills ? [...options.resources.skills] : undefined,
promptTemplates: options.resources?.promptTemplates ? [...options.resources.promptTemplates] : undefined,
};
this.streamOptions = { ...(options.streamOptions ?? {}) };
this.retryPolicy = options.retry ?? { enabled: false, maxRetries: 0, baseDelayMs: 1000 };
this.compactionSettings = options.compaction ?? {
enabled: true,
reserveTokens: 16384,
keepRecentTokens: 20000,
};
this.steeringMode = options.steeringMode ?? "one-at-a-time";
this.followUpMode = options.followUpMode ?? "one-at-a-time";
}
static async create(
options: AgentHarnessOptions,
): Promise<{ harness: AgentHarness; suspended: SuspendedOperation[] }> {
const [record] = await options.session.findRecords({ limit: 1 });
if (record !== undefined) throw new HarnessNotImplemented("create.restore");
return { harness: new AgentHarness(options), suspended: [] };
}
private unavailable<T>(operation: string): Promise<T> {
return Promise.reject(this.closed ? new HarnessClosed() : new HarnessNotImplemented(operation));
}
async getLeafId(): Promise<string | null> {
return this.durableSession.getLeafId();
}
async prompt(_text: string, _images?: ImageContent[]): Promise<RunResult>;
async prompt(_message: AgentMessage | AgentMessage[]): Promise<RunResult>;
async prompt(_input: string | AgentMessage | AgentMessage[], _images?: ImageContent[]): Promise<RunResult> {
return this.unavailable("prompt");
}
async skill(_name: string, _additionalInstructions?: string): Promise<RunResult> {
return this.unavailable("skill");View on GitHub (pinned to 4af9d21d3b)
Solutions
- Pass a brand-new, empty Session/SessionTree so findRecords returns nothing.
- Pre-check options.session.findRecords({ limit: 1 }) yourself and fail with your own error before calling create.
- Until create.restore ships, use the Agent class directly for resumable conversations and treat the harness as experimental (its prompt/steer/watch/etc. also reject with HarnessNotImplemented).
Example fix
// before
const { harness } = await AgentHarness.create({ session: existingSession }); // has records -> HarnessNotImplemented
// after
const [record] = await existingSession.findRecords({ limit: 1 });
if (record !== undefined) throw new Error("session restore not supported by this harness version");
const { harness } = await AgentHarness.create({ session: freshEmptySession }); Defensive patterns
Strategy: try-catch
Validate before calling
const [record] = await options.session.findRecords({ limit: 1 });
if (record !== undefined) {
// restore is unimplemented: use a fresh session instead
throw new Error("session has records; harness restore not implemented");
}
const { harness } = await AgentHarness.create(options); Type guard
function isHarnessNotImplemented(err: unknown, operation?: string): err is HarnessNotImplemented {
return err instanceof HarnessNotImplemented && (operation === undefined || err.operation === operation);
} Try / catch
try {
const { harness, suspended } = await AgentHarness.create(options);
} catch (err) {
if (err instanceof HarnessNotImplemented && err.operation === "create.restore") {
// fall back: create a fresh session, or use the Agent class directly
} else {
throw err;
}
} Prevention
- Only pass freshly created, empty sessions to AgentHarness.create in this version.
- Pre-check session.findRecords({ limit: 1 }) to fail with your own error message.
- Expect other harness methods (prompt, steer, watch, ...) to reject with HarnessNotImplemented too - treat the harness as experimental.
When it happens
Trigger: Passing a durable Session that already contains records (a previously used or persisted session tree) to AgentHarness.create(); reopening a session store on app restart and expecting resume; pointing AgentHarnessOptions.session at a shared or populated store.
Common situations: Apps that persist sessions and call create() on every startup; test fixtures reusing a session directory; upgrading to a harness version where restore simply has not shipped yet.
AI-assisted analysis of earendil-works/pi@4af9d21d3b (2026-08-24).
Data as JSON: /api/errors/d127645b915994c3.
Report an issue: GitHub.