hcengineering/platform · warning
request hang found
Error message
request hang found
What it means
For each active session request, the session tick checks how long it has been running; every hangRequestTimeoutSeconds it logs this warning with elapsed seconds, workspace, pending request count, user, and truncated request params. It identifies server-side requests (RPC) that never completed, typically because the client disconnected mid-request or the operation is genuinely stuck.
Source
Thrown at foundations/server/packages/server/src/sessionManager.ts:400
this.ctx.error('failed to close', err)
})
continue
}
if (
lastRequestDiff + (1 / 10) * lastRequestDiff > this.timeouts.pingTimeout &&
now - s.session.lastPing > this.timeouts.pingTimeout
) {
// We need to check state and close socket if it broken
// And ping other wize
s.session.lastPing = now
if (s.socket.checkState()) {
void s.socket.send(this.ticksContext, { result: pingConst }, s.session.binaryMode, s.session.useCompression)
}
}
for (const r of s.session.requests.values()) {
const sec = Math.round((now - r.start) / 1000)
if (sec > 0 && sec % hangRequestTimeoutSeconds === 0) {
this.ctx.warn('request hang found', {
sec,
wsId,
total: s.session.requests.size,
user: s.session.getUser(),
params: cutObjectArray(r.params)
})
}
}
}
}
}
createSession (token: Token, workspace: WorkspaceIds, info: LoginInfoWithWorkspaces): Session {
let primarySocialId: PersonId
let role: AccountRole = info.workspaces[workspace.uuid]?.role ?? AccountRole.User
switch (info.account) {
case systemAccountUuid:
primarySocialId = core.account.SystemView on GitHub (pinned to 63e28dc964)
Solutions
- Identify the stuck request via the logged params/wsId and profile the corresponding handler
- Optimize long-running queries or add streaming/pagination so they finish under the timeout
- Check downstream dependencies (datalake, DB, Kafka) for latency or deadlock
- Raise hangRequestTimeoutSeconds only if requests legitimately take longer; repeated warnings mean a real leak
Example fix
// before
await findAll(ctx, clazz, { limit: 1000000 })
// after
await findAll(ctx, clazz, { limit: 1000, ...page }) // paginate under timeout Defensive patterns
Strategy: try-catch
Validate before calling
const started = Date.now()
const result = await withTimeout(clientRequest, hangRequestTimeoutSeconds * 1000)
function withTimeout<T>(p: Promise<T>, ms: number): Promise<T> {
return Promise.race([p, new Promise<T>((_, rej) => setTimeout(() => rej(new Error('client-side request timeout')), ms))])
} Type guard
function isLongRunning(r: { start: number }, thresholdSec: number): boolean {
return (Date.now() - r.start) / 1000 > thresholdSec
} Try / catch
try {
await request
} catch (err) {
if (isTimeoutError(err)) {
logger.warn('request exceeded hang threshold', { elapsed: Date.now() - start })
// cancel and retry with smaller scope/pagination
} else throw err
} Prevention
- Paginate large findAll queries to keep requests short
- Add server-side timeouts to downstream calls (DB, storage)
- Include request ids in logs to correlate 'request hang found' entries
- Alert when the same request id is logged multiple ticks in a row
When it happens
Trigger: handleSessionTick iterates session.requests and finds a request whose start time exceeds a multiple of hangRequestTimeoutSeconds — long-running queries, deadlocks, or requests belonging to hung clients that will never read the response.
Common situations: Heavy queries over large workspaces exceeding the timeout; awaited downstream calls (storage, kafka, DB) blocked; clients disconnected while request still executing; repeated logs for the same request indicate a truly stuck operation.
Related errors
- session hang, closing...
- Wrong video options specified
- No video track found
- Workspace is closing
- Cannot find current person
AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29).
Data as JSON: /api/errors/88fee158bfbc078e.
Report an issue: GitHub.