overleaf/overleaf · error

invalid ?buildId

Error message

invalid ?buildId

What it means

_syncTeX validates ?buildId against /^[a-f0-9-]+$/ before calling CompileManager.promises.syncTeX. A missing, empty, or malformed buildId throws Error('invalid ?buildId'). The regex requires lowercase hex digits and hyphens only.

Source

Thrown at services/web/app/src/Features/Compile/CompileController.mjs:90

    res,
    'compile-with-checkpoint',
    { includeReferer: true }
  )

  return {
    compileFromHistory,
    pdfDownloadDomain,
    enablePdfCaching,
    pdfCachingMinChunkSize,
    enableCheckpoint,
  }
}

async function _syncTeX(req, res, direction, validatedOptions) {
  const projectId = req.params.Project_id
  const { editorId, buildId, clsiserverid: clsiServerId } = req.query
  if (!editorId?.match(/^[a-f0-9-]+$/)) throw new Error('invalid ?editorId')
  if (!buildId?.match(/^[a-f0-9-]+$/)) throw new Error('invalid ?buildId')

  const userId = CompileController._getUserIdForCompile(req)
  try {
    const body = await CompileManager.promises.syncTeX(projectId, userId, {
      direction,
      compileFromClsiCache: Features.hasFeature('saas'),
      validatedOptions: {
        ...validatedOptions,
        editorId,
        buildId,
      },
      clsiServerId,
    })
    res.json(body)
  } catch (err) {
    if (err instanceof Errors.NotFoundError) return res.status(404).end()
    throw err
  }

View on GitHub (pinned to 28ad3b03b7)

Solutions

  1. Only issue synctex requests after a compile has returned a buildId; guard the client call.
  2. Normalize the buildId to the server's format (lowercase hex with hyphens) before sending.
  3. If building deep links, include the current buildId in the URL.
  4. Catch this error client-side and trigger a recompile to obtain a valid buildId.

Example fix

// before
fetch(`/project/${projectId}/sync/pdf?buildId=${buildId}&page=${page}`)
// after
if (!/^[a-f0-9-]+$/.test(buildId ?? '')) {
  await recompile() // get a fresh valid buildId
}
fetch(`/project/${projectId}/sync/pdf?buildId=${buildId}&page=${page}`)
Defensive patterns

Strategy: validation

Validate before calling

const BUILD_ID_RE = /^[a-f0-9-]+$/
if (!BUILD_ID_RE.test(buildId ?? '')) { await recompile(); /* use new buildId */ }

Type guard

function isBuildId(v) { return typeof v === 'string' && /^[a-f0-9-]+$/.test(v) }

Try / catch

try {
  await syncTeX({ buildId })
} catch (err) {
  if (err.message === 'invalid ?buildId') {
    await recompileAndRetry()
  } else throw err
}

Prevention

When it happens

Trigger: Calling the synctex proxy endpoints with ?buildId absent, empty, uppercase, or containing illegal characters (e.g. buildId=123, buildId=null, buildId with URL-encoded slashes).

Common situations: Frontend sends a buildId captured before the first successful compile (undefined); stale client code still using the old requestType/token params; buildId stored with uppercase letters from a different ID format; deep links to synctex with the param stripped.

Understand the failure class

Background: "Invalid query parameter" / "Failed to parse value of ...": fixing bad query string parameters across APIs — this error's family across 36 libraries.

Related errors


AI-assisted analysis of overleaf/overleaf@28ad3b03b7 (2026-09-03). Data as JSON: /api/errors/294564a0ca313148. Report an issue: GitHub.