apify/crawlee · error · Error
Could not derive the default values of the custom statistics
Error message
Could not derive the default values of the custom statistics fields from `stateExtension.deserialize` - give every field a default, or declare `stateExtension.defaultState` explicitly.
What it means
Statistics must know the default values of every custom stateExtension field to initialize its state. When only a deserialize function is provided and it cannot be invoked synchronously to derive defaults on an empty object, the library throws this error. Provide per-field defaults or an explicit defaultState.
Source
Thrown at packages/core/src/crawlers/statistics.ts:438
const { defaultState, deserialize } = options;
if (typeof defaultState === 'function') {
return defaultState;
}
if (defaultState !== undefined) {
return () => structuredClone(defaultState);
}
if (deserialize === undefined) {
return () => ({}) as StateExtension;
}
return () => {
try {
return convertStateSync(deserialize, {}, this.#persistStateKey);
} catch (error) {
throw new Error(
'Could not derive the default values of the custom statistics fields from `stateExtension.deserialize` - ' +
'give every field a default, or declare `stateExtension.defaultState` explicitly.',
{ cause: error },
);
}
};
}
/** The built-in half of {@apilink Statistics.defaultState}, before any custom fields are merged over it. */
#builtInDefaultState(): StatisticState {
return {
requestsFinished: 0,
requestsFailed: 0,
requestsRetries: 0,
requestsFailedPerMinute: 0,
requestsFinishedPerMinute: 0,
requestMinDurationMillis: Infinity,
requestMaxDurationMillis: 0,View on GitHub (pinned to dbe57fb09c)
Solutions
- Declare `stateExtension.defaultState` explicitly with a value for every field
- Make deserialize return defaults when given an empty object (e.g. spread defaults)
- Check the `cause` on this error to see why convertStateSync failed
- Avoid async deserializers in stateExtension
Example fix
// before
stateExtension: { deserialize: async (s) => JSON.parse(s) }
// after
stateExtension: { defaultState: { myCounter: 0 }, deserialize: (s) => JSON.parse(s) } Defensive patterns
Strategy: validation
Validate before calling
if (!stateExtension.defaultState && isAsyncLike(stateExtension.deserialize)) throw new Error('provide stateExtension.defaultState'); Try / catch
try { new Statistics({ stateExtension }); } catch (e) { if (String(e).includes('Could not derive the default values')) addExplicitDefaultState(); else throw e; } Prevention
- Always provide explicit defaultState for custom extensions
- Keep deserialize synchronous
- Test Statistics construction with your extension in unit tests
When it happens
Trigger: Passing stateExtension with a deserialize that fails or is async/ambiguous when called on {} (no defaultState provided), during Statistics construction.
Common situations: Writing deserialize that assumes pre-populated input; providing an async deserializer; forgetting defaultState after refactoring the extension shape.
Related errors
- The custom statistics field `${String(key)}` collides with a
- The `minConcurrency`/`maxConcurrency`/`initialConcurrency`/`
- The `requestManager` option cannot be used in conjunction wi
- Cannot decide what to purge before running again: `sameDomai
- Failed to infer format from the path: '${path}'. Supported f
AI-assisted analysis of apify/crawlee@dbe57fb09c (2026-08-30).
Data as JSON: /api/errors/0ebc9089431e5d12.
Report an issue: GitHub.