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
- Only issue synctex requests after a compile has returned a buildId; guard the client call.
- Normalize the buildId to the server's format (lowercase hex with hyphens) before sending.
- If building deep links, include the current buildId in the URL.
- 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
- Gate synctex calls behind a 'compile completed' flag holding a valid buildId.
- Never persist/restore stale buildIds across sessions without revalidation.
- Mirror the server regex in client-side validation.
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
- invalid ?editorId
- invalid page parameter
- missing file parameter
- invalid line parameter
- invalid column parameter
AI-assisted analysis of overleaf/overleaf@28ad3b03b7 (2026-09-03).
Data as JSON: /api/errors/294564a0ca313148.
Report an issue: GitHub.