santifer/career-ops · error · Error

apify: entry has invalid field_map. Each of title, url…

Error message

apify: entry ${entry.name} has invalid field_map. Each of title, url, company, location, description must be a string or a non-empty array of strings. title and url are required.

What it means

The apify plugin validates each entry's field_map: title and url are required, and title, url, company, location, description (when present) must each be a string or a non-empty array of strings. Any violation throws this descriptive error.

Solutions

  1. Ensure title and url are present and each field is a string or non-empty array of strings, e.g. field_map: { title: 'positionName', url: 'url', company: ['company','name'] }.
  2. Remove optional fields (company/location/description) entirely rather than setting them to invalid values.
  3. Check the dataset's actual output fields in the Apify console and map to real key names.
  4. Validate the YAML/JSON parses as intended (indentation can turn strings into nested structures).

Example fix

// before
field_map:
  title:
  url: url
  company: []
// after
field_map:
  title: positionName
  url: url
  company: company
Defensive patterns

Strategy: validation

Validate before calling

const isFieldSpec = (v) => typeof v === 'string' || (Array.isArray(v) && v.length > 0 && v.every(x => typeof x === 'string'));
if (!isFieldSpec(entry.field_map?.title) || !isFieldSpec(entry.field_map?.url)) throw new Error('invalid field_map');

Type guard

const validFieldMap = (fm) => !!fm && isFieldSpec(fm.title) && isFieldSpec(fm.url) && ['company','location','description'].every(k => fm[k] == null || isFieldSpec(fm[k]));

Try / catch

try {
  await scanner.run(config);
} catch (e) {
  if (String(e.message).includes('invalid field_map')) {
    console.error('Check field_map: strings or non-empty string arrays; title & url required');
  }
  throw e;
}

Prevention

When it happens

Trigger: Config entry where field_map is absent, title/url missing, or any mapped field is a number, empty array, nested object, or array containing non-strings.

Common situations: Writing field_map values as comma-separated strings expecting splitting; leaving an empty array after removing a dataset field; typo'ing a key (e.g. feild_map); specifying company: [] for optional fields.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of santifer/career-ops@aac998c7ed (2026-09-16). Data as JSON: /api/errors/2a26e3b8b0a8685f. Report an issue: GitHub.

Appendix: source

Thrown at plugins/apify/index.mjs:195

    detect() { return null; },

    async fetch(entry, ctx) {
      const token = ctx?.env?.APIFY_TOKEN || process.env.APIFY_TOKEN;
      if (!hasToken(token)) {
        throw new Error('APIFY_TOKEN not set — enable apify in config/plugins.yml and add the token to .env');
      }
      if (!entry.actor) {
        throw new Error(`apify: entry ${entry.name} missing 'actor' (e.g. misceres/indeed-scraper)`);
      }
      if (
        !entry.field_map ||
        !isFieldSpec(entry.field_map.title) ||
        !isFieldSpec(entry.field_map.url) ||
        (entry.field_map.company != null && !isFieldSpec(entry.field_map.company)) ||
        (entry.field_map.location != null && !isFieldSpec(entry.field_map.location)) ||
        (entry.field_map.description != null && !isFieldSpec(entry.field_map.description))
      ) {
        throw new Error(
          `apify: entry ${entry.name} has invalid field_map. Each of title, url, company, ` +
          `location, description must be a string or a non-empty array of strings. title and url are required.`
        );
      }

      const opts = { token };
      if (entry.timeout_ms != null) opts.timeoutMs = entry.timeout_ms;
      const items = await runActor(entry.actor, entry.input || {}, opts);

      const useLocalJd = entry.field_map.description != null;
      const sourceLabel = String(entry.actor || 'apify').replace(/[^a-z0-9]+/gi, '-').toLowerCase();

      return items
        .map(item => {
          const normalized = normalizeItem(item, entry.field_map, entry.defaults);
          if (!normalized.title || !normalized.url) return null;
          if (!isHttpsUrl(normalized.url)) return null;
          if (!useLocalJd) return normalized;

View on GitHub (pinned to aac998c7ed)