Crosstalk-Solutions/project-nomad · error · Error

Failed to dispatch download job

Error message

Failed to dispatch download job

What it means

downloadRemote delegates the actual fetch to a download job system (dispatchDownloadJob-like call with forceNew and resourceMetadata). If that dispatcher returns a result without a job object, the service cannot proceed and throws this error, meaning the job queue accepted the request but produced no job record.

Solutions

  1. Inspect server logs immediately before this line for the dispatcher's underlying error
  2. Verify the job queue backend (DB/Redis) is up and the run_download_jobs table exists (run migrations)
  3. Reproduce by calling downloadRemote after confirming dispatch works for other filetypes
  4. Retry the call once transient queue issues are resolved
Defensive patterns

Strategy: try-catch

Try / catch

try { const res = await mapService.downloadRemote(url) } catch (e) { if (e instanceof Error && e.message === 'Failed to dispatch download job') { /* inspect job queue backend health, then surface to user */ } throw e }

Prevention

When it happens

Trigger: Calling downloadRemote when the job dispatch layer fails internally — e.g. database/queue unavailable, job creation rejected, or the dispatcher returns { job: null } due to an unexpected filetype/metadata combination.

Common situations: Job queue (DB/Redis) not running or misconfigured; migrations for the run-download-jobs table not applied; version mismatch between map_service and the job dispatcher API; concurrent dispatch hitting a unique constraint that swallows the job.

Related errors


AI-assisted analysis of Crosstalk-Solutions/project-nomad@0bd1c6f4f9 (2026-08-27). Data as JSON: /api/errors/d3629b4378e463e2. Report an issue: GitHub.

Appendix: source

Thrown at admin/app/services/map_service.ts:303

    // Parse resource metadata
    const parsedFilename = CollectionManifestService.parseMapFilename(filename)
    const resourceMetadata = parsedFilename
      ? { resource_id: parsedFilename.resource_id, version: parsedFilename.version, collection_ref: null }
      : undefined

    // Dispatch background job
    const result = await RunDownloadJob.dispatch({
      url,
      filepath,
      timeout: 30000,
      allowedMimeTypes: PMTILES_MIME_TYPES,
      forceNew: true,
      filetype: 'map',
      resourceMetadata,
    })

    if (!result.job) {
      throw new Error('Failed to dispatch download job')
    }

    logger.info(`[MapService] Dispatched download job ${result.job.id} for URL ${url}`)

    return {
      filename,
      jobId: result.job?.id,
    }
  }

  async downloadRemotePreflight(
    url: string
  ): Promise<{ filename: string; size: number } | { message: string }> {
    try {
      assertNotPrivateUrl(url)
      const parsed = new URL(url)
      if (!parsed.pathname.endsWith('.pmtiles')) {
        throw new Error(`Invalid PMTiles file URL: ${url}. URL must end with .pmtiles`)

View on GitHub (pinned to 0bd1c6f4f9)