apify/crawlee · error
Compilation result is not a function!
Error message
Compilation result is not a function!
What it means
compileScript() evaluates a string of JavaScript via vm.runInNewContext() and expects the result to be a callable function. This error means the script string evaluated successfully but returned something other than a function (e.g. an object, number, or undefined). The library uses the result as a request interceptor/handler, so a non-function is unusable and the code throws defensively ('This should not happen...').
Source
Thrown at packages/puppeteer-crawler/src/internals/utils/puppeteer_utils.ts:477
* still execute in the main process via prototype manipulation. Therefore you
* should only use this function to execute sanitized or safe code.
*
* Custom context may also be provided using the `context` parameter. To improve security,
* make sure to only pass the really necessary objects to the context. Preferably making
* secured copies beforehand.
*/
export function compileScript(scriptString: string, context: Dictionary = Object.create(null)): CompiledScriptFunction {
const funcString = `async ({ page, request }) => {${scriptString}}`;
let func;
try {
func = vm.runInNewContext(funcString, context); // "Secure" the context by removing prototypes, unless custom context is provided.
} catch (err) {
getLog().exception(err as Error, 'Cannot compile script!');
throw err;
}
if (typeof func !== 'function') throw new Error('Compilation result is not a function!'); // This should not happen...
return func;
}
/**
* Extended version of Puppeteer's `page.goto()` allowing to perform requests with HTTP method other than GET,
* with custom headers and POST payload. URL, method, headers and payload are taken from
* request parameter that must be an instance of Request class.
*
* *NOTE:* In recent versions of Puppeteer using requests other than GET, overriding headers and adding payloads disables
* browser cache which degrades performance.
*
* @param page Puppeteer [`Page`](https://pptr.dev/api/puppeteer.page) object.
* @param request
* @param [gotoOptions] Custom options for `page.goto()`.
*/
export async function gotoExtended(
page: Page,View on GitHub (pinned to dbe57fb09c)
Solutions
- Ensure the script string evaluates to a function, e.g. '() => { ... }' or 'async function intercept(request) { ... }'
- Log the evaluated result (typeof vm.runInNewContext(script)) during development to confirm it is 'function'
- Check the script source for truncation or escaping problems (quotes, template literals) when loading from config/env
- If the script intentionally returns a value, wrap it: '(' + expression + ')' and verify it returns a callable
Example fix
// before
await page.setRequestInterception(compileScript('request.continue()'));
// after
await page.setRequestInterception(compileScript('async ({ request }) => { await request.continue(); }')); Defensive patterns
Strategy: validation
Validate before calling
function isScriptAFunction(src) {
try {
const sandbox = { console };
return typeof require('vm').runInNewContext(src, sandbox) === 'function';
} catch { return false; }
}
if (!isScriptAFunction(myScript)) throw new TypeError('interception script must evaluate to a function'); Type guard
const isFn = (v) => typeof v === 'function';
Try / catch
try {
const func = compileScript(script);
} catch (err) {
log.error('script did not compile to a function', { script: script.slice(0, 200) });
throw err;
} Prevention
- Always author interception scripts as function expressions, e.g. 'async ({ request }) => { ... }'
- Smoke-test scripts in a vm sandbox before deploying
- Avoid loading scripts from loosely-validated env/config where quoting can break
- Unit-test compileScript output type in CI
When it happens
Trigger: Calling compileScript (directly or via page.setRequestInterception helpers) with a script string whose body evaluates to a non-function value — e.g. the string is a bare expression like '1+1', an object literal, an async arrow missing parentheses, or the script was truncated so the function declaration never completes.
Common situations: Users storing interception scripts in files/env vars that get mangled (quotes stripped, newlines lost), passing a snippet copied as an expression instead of a function definition, or upgrading Crawlee where compileScript previously tolerated non-function results.
Related errors
- PuppeteerCrawlerOptions.launchContext.proxyUrl is not allowe
- 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/6dbc9d91d34ec25f.
Report an issue: GitHub.