apify/crawlee · error · Error
The state conversion for '${persistStateKey}' validated asyn
Error message
The state conversion for '${persistStateKey}' validated asynchronously, which this caller cannot await. What it means
RecoverableState validates its persisted state through a Standard Schema converter, but convertStateSync only supports validators whose validate() returns results synchronously. If the schema's validate() returned a Promise (detected via 'then' in result), the synchronous callers (#resolveDefaultStateExtension, #restoreStateExtension, #serializeStateExtension) cannot await it, so it throws rather than silently skipping validation.
Source
Thrown at packages/core/src/recoverable_state.ts:46
/**
* Applies a {@apilink SyncStateConversion}, throwing a {@apilink StateValidationError} for a schema that rejects
* the value.
*
* @internal
*/
export function convertStateSync<TFrom, TTo>(
conversion: SyncStateConversion<TFrom, TTo>,
value: TFrom,
persistStateKey: string,
): TTo {
if (typeof conversion === 'function') {
return conversion(value);
}
const result = conversion['~standard'].validate(value);
if ('then' in result) {
throw new Error(
`The state conversion for '${persistStateKey}' validated asynchronously, which this caller cannot await.`,
);
}
if (result.issues) {
throw new StateValidationError(persistStateKey, result.issues);
}
return result.value;
}
export interface RecoverableStatePersistenceOptions {
/**
* The key under which the state is stored in the KeyValueStore
*/
persistStateKey: string;
/**View on GitHub (pinned to dbe57fb09c)
Solutions
- Replace the schema with a purely synchronous one (no async refinements/transforms) for the given persistStateKey.
- Remove async validation logic (e.g. z.string().refine(async ...) or async superRefinement) from the state schema.
- Pre-validate the value synchronously before handing it to RecoverableState.
- If async validation is unavoidable, perform it yourself before/around state restore instead of relying on the sync converter.
Example fix
// before
const schema = z.object({ at: z.string() }).refine(async (v) => checkRemote(v)); // async validate
// after
const schema = z.object({ at: z.string() }).refine((v) => !Number.isNaN(Date.parse(v.at))); // sync validate Defensive patterns
Strategy: validation
Validate before calling
// Ensure the schema validates synchronously before handing it to RecoverableState
const result = schema['~standard'].validate(value);
if (result instanceof Promise || 'then' in (result as any)) {
throw new Error('State schema must validate synchronously (no async refinements)');
} Type guard
function isSyncStandardSchema<T>(s: unknown): s is StandardSchemaV1<T> {
try {
const r = (s as any)['~standard'].validate(undefined);
return !(r instanceof Promise) && !('then' in r);
} catch { return false; }
} Try / catch
try {
await state.initialize();
} catch (err) {
if ((err as Error).message.includes('validated asynchronously')) {
throw new Error(`Schema for '${persistStateKey}' uses async validation; make it synchronous`);
}
throw err;
} Prevention
- Avoid async refinements/transforms in persisted-state schemas.
- Prefer synchronous schema libraries or sync mode for state validation.
- Test state schemas with validate() and assert the result is not a Promise.
- Do heavy async checks outside the schema, before state restore.
When it happens
Trigger: Providing a conversion/schema (e.g. an async Standard Schema implementation or a zod schema behind an async adapter) whose `~standard.validate` returns a thenable, then loading/serializing the RecoverableState (initialize/serialize paths).
Common situations: Using a schema library configured for async validation (async refinements/transforms); wrapping the converter so validate returns a Promise; switching schema implementations while keeping the sync recovery path.
Related errors
- StateValidationError(persistStateKey, result.issues)
- StateValidationError(this.#persistStateKey, result.issues)
- RequestValidationError(label, result.issues)
- Failed to infer format from the path: '${path}'. Supported f
- Unsupported format: '${format}'. Use one of ${supportedForma
AI-assisted analysis of apify/crawlee@dbe57fb09c (2026-08-30).
Data as JSON: /api/errors/d3738450b4a178a2.
Report an issue: GitHub.