santifer/career-ops · error · Error

APIFY_TOKEN not set

Error message

APIFY_TOKEN not set

What it means

Thrown by `runActor` (plugins/apify/_apify.mjs:188) at the very top of the function when no token is supplied. The token defaults to `process.env.APIFY_TOKEN`; if that is unset AND no explicit `token` option is passed, the function refuses to proceed before making any network call. This prevents an anonymous request that would silently fail later. Note the provider-level wrapper (index.mjs) has its own richer message (error 115); this lower-level guard catches direct callers of runActor.

Source

Thrown at plugins/apify/_apify.mjs:188

}

async function fetchDatasetItems(runId, token, deadline = null) {
  const url = `${APIFY_API_BASE}/actor-runs/${runId}/dataset/items`;
  const items = await fetchJson(
    url,
    { headers: authHeaders(token) },
    PER_REQUEST_TIMEOUT_MS * 2,
    CONNECT_RETRY_ATTEMPTS,
    deadline,
  );
  if (!Array.isArray(items)) {
    throw new Error(`Apify run ${runId} returned non-array dataset payload`);
  }
  return items;
}

export async function runActor(actorId, input, { timeoutMs = DEFAULT_RUN_TIMEOUT_MS, token = process.env.APIFY_TOKEN } = {}) {
  if (!token) throw new Error('APIFY_TOKEN not set');
  if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
    throw new Error(`apify: invalid timeoutMs ${JSON.stringify(timeoutMs)} (must be a positive finite number of milliseconds)`);
  }
  // Single deadline shared across startRun → waitForRun → fetchDatasetItems so
  // the caller's timeoutMs is the end-to-end ceiling, not just the wait loop.
  const deadline = Date.now() + timeoutMs;
  const runId = await startRun(actorId, input, token, deadline);
  const run = await waitForRun(runId, token, deadline, timeoutMs);
  if (run.status !== 'SUCCEEDED') {
    const reason = run.statusMessage ? `: ${run.statusMessage}` : '';
    throw new Error(`Apify actor ${actorId} finished with status ${run.status}${reason}`);
  }
  return await fetchDatasetItems(runId, token, deadline);
}

View on GitHub (pinned to 9b17a8ac97)

Solutions

  1. Set APIFY_TOKEN in .env and ensure the env loader runs before calling runActor.
  2. Pass the token explicitly: `runActor(actorId, input, { token })`.
  3. In CI, inject APIFY_TOKEN as a secret environment variable.
  4. Verify with `node -e "console.log(Boolean(process.env.APIFY_TOKEN))"` in the same process context.

Example fix

// before
import { runActor } from './plugins/apify/_apify.mjs';
await runActor('misceres/indeed-scraper', {}); // throws: APIFY_TOKEN not set
// after
import 'dotenv/config';
await runActor('misceres/indeed-scraper', {}); // token read from process.env.APIFY_TOKEN
Defensive patterns

Strategy: validation

Validate before calling

function assertApifyToken(env = process.env) {
  if (!env.APIFY_TOKEN) {
    throw new Error('APIFY_TOKEN missing — add it to .env before running apify scans.');
  }
}
assertApifyToken();

Type guard

/** @param {unknown} env */
function hasApifyToken(env) {
  return typeof env?.APIFY_TOKEN === 'string' && env.APIFY_TOKEN.length > 0;
}

Try / catch

if (!process.env.APIFY_TOKEN) {
  console.error('Skipping apify scan: APIFY_TOKEN not set. Add it to .env.');
} else {
  await runActor(actorId, input, opts);
}

Prevention

When it happens

Trigger: `runActor(actorId, input)` or `runActor(actorId, input, {})` is called when `process.env.APIFY_TOKEN` is undefined/empty. The guard `if (!token)` fires immediately.

Common situations: Running a script that calls runActor directly without loading .env; CI environment missing the secret; .env not loaded because the process was started without the env loader; the provider plugin's ctx.env did not propagate the token to a direct runActor call.

Related errors


AI-assisted analysis of santifer/career-ops@9b17a8ac97 (2026-08-13). Data as JSON: /api/errors/5cdd949ec5d56403. Report an issue: GitHub.