santifer/career-ops · error · Error

teamtailor: cannot derive jobs.rss URL for ${fallbackCompany

Error message

teamtailor: cannot derive jobs.rss URL for ${fallbackCompany(entry)}

What it means

resolveFeedUrl returns null when there is no api/careers_url, the URL cannot be parsed, the protocol is not https, or — for non-explicit entries — the host is not *.teamtailor.com. fetch then throws because no /jobs.rss URL can be derived. detect() only claims *.teamtailor.com hosts, so a branded-domain entry without provider: teamtailor reaches fetch only via an explicit override.

Source

Thrown at providers/teamtailor.mjs:86

function fallbackCompany(entry) {
  return typeof entry?.name === 'string' && entry.name.trim() ? entry.name.trim() : 'Teamtailor';
}

/** @type {Provider} */
export default {
  id: 'teamtailor',

  detect(entry) {
    // Auto-detection never claims a branded host — only *.teamtailor.com.
    const url = resolveFeedUrl(entry, { explicit: false });
    return url ? { url } : null;
  },

  async fetch(entry, ctx) {
    const explicit = entry?.provider === 'teamtailor';
    const feedUrl = resolveFeedUrl(entry, { explicit });
    if (!feedUrl) throw new Error(`teamtailor: cannot derive jobs.rss URL for ${fallbackCompany(entry)}`);
    assertFeedUrl(feedUrl, { explicit });
    // redirect:'error' prevents SSRF via server-side redirects; combined with
    // assertFeedUrl above it keeps the request pinned to the trusted host
    // (*.teamtailor.com, or the branded host the user explicitly configured).
    const text = await ctx.fetchText(feedUrl, { redirect: 'error' });
    return parseTeamtailorFeed(text, fallbackCompany(entry));
  },
};

function fromCodePoint(cp) {
  try {
    return String.fromCodePoint(cp);
  } catch {
    return '';
  }
}

// Decode the XML entities that appear in RSS text: numeric (& / ')

View on GitHub (pinned to 9b17a8ac97)

Solutions

  1. Set api or careers_url to a valid https URL (canonical: https://<slug>.teamtailor.com, branded: https://careers.acme.com with provider: teamtailor)
  2. Ensure the scheme is https://
  3. Confirm provider: teamtailor is present if you use a branded host
  4. If the company is not on Teamtailor, remove the provider tag

Example fix

# before
- name: Acme
  provider: teamtailor
# after
- name: Acme
  provider: teamtailor
  careers_url: https://careers.acme.com
Defensive patterns

Strategy: validation

Validate before calling

// Run detect() first; a null result means fetch will throw 'cannot derive'.
import tt from './providers/teamtailor.mjs';
if (!tt.detect(entry) && entry.provider !== 'teamtailor') {
  console.warn(`${entry.name}: teamtailor cannot derive jobs.rss — check URL/provider`);
}

Prevention

When it happens

Trigger: An explicit provider: teamtailor entry whose api/careers_url is missing, malformed, or non-https; or an auto-detected entry that detect should have rejected but fetch was called directly. Also a bare *.teamtailor.com URL with an empty path still resolves fine, so this is specifically about bad/missing input.

Common situations: provider: teamtailor is set on an entry but the URL line was omitted/mis-indented; the branded URL is http://; or the entry was constructed programmatically without a URL.

Related errors


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