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

  1. Ensure the script string evaluates to a function, e.g. '() => { ... }' or 'async function intercept(request) { ... }'
  2. Log the evaluated result (typeof vm.runInNewContext(script)) during development to confirm it is 'function'
  3. Check the script source for truncation or escaping problems (quotes, template literals) when loading from config/env
  4. 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

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


AI-assisted analysis of apify/crawlee@dbe57fb09c (2026-08-30). Data as JSON: /api/errors/6dbc9d91d34ec25f. Report an issue: GitHub.