FlowiseAI/Flowise · error · Error
Error saving checkpoint
Error message
Error saving checkpoint
What it means
MySQLSaver.put wraps the INSERT ... ON DUPLICATE KEY UPDATE; any DB or serde.stringify error is logged via console.error and re-thrown generically. The connection is destroyed in finally.
Source
Thrown at packages/components/nodes/memory/AgentMemory/MySQLAgentMemory/mysqlSaver.ts:191
const queryRunner = dataSource.createQueryRunner()
const row = [
config.configurable?.thread_id || this.threadId,
checkpoint.id,
config.configurable?.checkpoint_id,
Buffer.from(this.serde.stringify(checkpoint)), // Encode to binary
Buffer.from(this.serde.stringify(metadata)) // Encode to binary
]
const tableName = this.sanitizeTableName(this.tableName)
const query = `INSERT INTO ${tableName} (thread_id, checkpoint_id, parent_id, checkpoint, metadata)
VALUES (?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE checkpoint = VALUES(checkpoint), metadata = VALUES(metadata)`
await queryRunner.manager.query(query, row)
await queryRunner.release()
} catch (error) {
console.error('Error saving checkpoint', error)
throw new Error('Error saving checkpoint')
} finally {
await dataSource.destroy()
}
return {
configurable: {
thread_id: config.configurable?.thread_id || this.threadId,
checkpoint_id: checkpoint.id
}
}
}
async delete(threadId: string): Promise<void> {
if (!threadId) return
const dataSource = await this.getDataSource()
await this.setup(dataSource)
const tableName = this.sanitizeTableName(this.tableName)View on GitHub (pinned to abe4a8601a)
Solutions
- Check console logs to distinguish a serde failure from a DB failure.
- Raise max_allowed_packet on the MySQL server if payloads are large.
- Ensure checkpoint/metadata are serializable (no functions, circular refs, BigInt).
- Verify connection stability and INSERT/UPDATE privileges.
Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-serialise to fail before hitting the DB on non-serializable state
function assertSerializable(value: unknown): void {
structuredClone(value) // throws on non-cloneable (functions, etc.)
JSON.stringify(value) // throws on circular refs
} Try / catch
try {
await saver.put(config, checkpoint, metadata)
} catch (e) {
if (/Error saving checkpoint/.test((e as Error).message)) {
// inspect logs: serde vs DB; raise max_allowed_packet if payload too large
}
throw e
} Prevention
- Keep checkpoint state JSON-serializable (no functions, BigInt, circular refs).
- Raise max_allowed_packet for large graph states.
- Verify INSERT/UPDATE privileges and connection stability.
- Log the original error from console.error to triage quickly.
When it happens
Trigger: checkpoint/metadata payload too large for the BLOB / max_allowed_packet; serde.stringify throws on a non-serializable checkpoint; connection lost mid-write; PK conflict edge cases.
Common situations: Very large graph state exceeding MySQL packet size; non-serializable value in checkpoint metadata; flaky connection during a write; concurrent writes racing on the same checkpoint_id.
Related errors
- Error retrieving ${this.tableName}
- Error listing checkpoints
- Error creating ${this.tableName} table
- Invalid JSON in the Additional Configuration:
- Invalid table name
AI-assisted analysis of FlowiseAI/Flowise@abe4a8601a (2026-08-12).
Data as JSON: /api/errors/9014eef64ebf6865.
Report an issue: GitHub.