apify/crawlee · error

The "urls" parameter must be an array

Error message

The "urls" parameter must be an array

What it means

emailsFromUrls expects an array of URL strings and asserts Array.isArray(urls) at entry. Passing anything else (string, object, null, undefined) throws this synchronously as an input contract violation. This is a defensive check to fail fast on wrong argument types.

Source

Thrown at packages/utils/src/internals/social.ts:45

 * @param text Text to search in.
 * @return Array of emails addresses found.
 * If no emails are found, the function returns an empty array.
 */
export function emailsFromText(text: string): string[] {
    if ((typeof text as unknown) !== 'string') return [];
    return text.match(EMAIL_REGEX_GLOBAL) || [];
}

/**
 * The function extracts email addresses from a list of URLs.
 * Basically it looks for all `mailto:` URLs and returns valid email addresses from them.
 * Note that the function preserves the order of emails and keep duplicates.
 * @param urls Array of URLs.
 * @return Array of emails addresses found.
 * If no emails are found, the function returns an empty array.
 */
export function emailsFromUrls(urls: string[]): string[] {
    if (!Array.isArray(urls)) throw new Error('The "urls" parameter must be an array');
    const emails: string[] = [];

    for (const url of urls) {
        if (!url) continue;
        if (!EMAIL_URL_PREFIX_REGEX.test(url)) continue;

        const email = url.replace(EMAIL_URL_PREFIX_REGEX, '').trim();
        if (EMAIL_REGEX.test(email)) emails.push(email);
    }

    return emails;
}

// Supports URLs starting with `tel://`, `tel:/` and `tel:`, and similarly `phone`, `telephone` and `callto`
const PHONE_URL_PREFIX_REGEX = /^(tel|phone|telephone|callto):(\/)?(\/)?/i;

// It's pretty much impossible (and unmaintainable) to have just one large regular expression for all possible phone numbers.
// So here we define various regular expression for typical phone number patterns, which are then used to compile

View on GitHub (pinned to dbe57fb09c)

Solutions

  1. Wrap the input in an array: emailsFromUrls([url])
  2. Add a TypeScript type annotation/checked call so tsc catches non-array args
  3. Validate with Array.isArray before calling
  4. Check the upstream producer actually returns an array (log/inspect it)

Example fix

// before
const emails = emailsFromUrls('https://example.com/contact');

// after
const emails = emailsFromUrls(['https://example.com/contact']);
Defensive patterns

Strategy: type-guard

Validate before calling

if (!Array.isArray(urls)) throw new TypeError('emailsFromUrls expects an array of URL strings');
if (urls.some((u) => typeof u !== 'string')) throw new TypeError('all items must be strings');

Type guard

function isStringArray(v: unknown): v is string[] {
  return Array.isArray(v) && v.every((x) => typeof x === 'string');
}

Try / catch

try {
  emails = emailsFromUrls(input as string[]);
} catch (err) {
  if (String(err).includes('must be an array')) emails = emailsFromUrls([String(input)]);
  else throw err;
}

Prevention

When it happens

Trigger: Calling emailsFromUrls with a single URL string instead of an array (e.g. emailsFromUrls('https://site.com/contact')), or with a non-array value from an untyped/unvalidated code path.

Common situations: JavaScript users (no type checking) passing one URL directly; passing an object like { urls: [...] }; passing a result of a function that may return undefined; refactoring from emailsFromString to emailsFromUrls without wrapping the input.

Related errors


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