hcengineering/platform · error

err.message

Error message

err.message

What it means

A 500 response whose body echoes err.message from the catch block of the integration-state GET handler. Any exception thrown by getState (DB errors, downstream service failures, bad auth) surfaces here as a generic 500.

Source

Thrown at services/gmail/pod-gmail/src/main.ts:199

            res.status(401).send()
            return
          }

          const { workspace } = decodeToken(token)
          const socialId = req.query.socialId as PersonId | undefined
          if (socialId == null || socialId === '') {
            res.status(400).send({ error: 'Missing socialId param' })
            return
          }
          const state = await gmailController.getState(workspace, socialId)
          if (state === undefined) {
            res.status(404).send({ error: 'No gmail clients found for social id' })
            return
          }
          res.send(state)
        } catch (err: any) {
          ctx.error('Failed to get integration state', { message: err.message })
          res.status(500).send({ error: err.message })
        }
      }
    },
    {
      endpoint: '/start-sync',
      type: 'post',
      handler: async (req, res) => {
        try {
          const token = extractToken(req.headers)

          if (token === undefined) {
            res.status(401).send()
            return
          }

          const { workspace } = decodeToken(token)
          const socialId = req.query.socialId as PersonId | undefined
          ctx.info('Sync request received', { workspace, socialId })

View on GitHub (pinned to 63e28dc964)

Solutions

  1. Check the service logs for the 'Failed to get integration state' ctx.error entry to see the underlying cause
  2. Verify the database/storage backing gmailController is reachable and migrated
  3. Confirm the auth token is valid — decodeToken may throw before state lookup
  4. Add more specific error handling for known failure modes instead of blindly returning err.message

Example fix

// before
} catch (err: any) {
  res.status(500).send({ error: err.message })
}
// after
} catch (err: any) {
  ctx.error('Failed to get integration state', { message: err.message })
  res.status(500).send({ error: 'Internal error retrieving integration state' })
}
Defensive patterns

Strategy: try-catch

Validate before calling

// verify preconditions before calling
if (!workspace || !socialId) throw new Error('workspace and socialId required')

Type guard

function isErrorResponse(res: Response): res is Response & { ok: false } {
  return !res.ok
}

Try / catch

try {
  const res = await fetch(url)
  if (!res.ok) {
    const body = await res.json()
    throw new Error(`integration-state 500: ${body.error ?? 'unknown'}`)
  }
  return await res.json()
} catch (e) {
  // retry with backoff; 500 may be transient storage failure
}

Prevention

When it happens

Trigger: getState throws — e.g. database unreachable, storage/dal exceptions, or unexpected undefined fields — while handling GET /integration-state.

Common situations: Database outages or migrations, network partitions to storage, TypeError inside the controller when partial state exists, auth token decode errors bubbling up.

Related errors


AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29). Data as JSON: /api/errors/ee0224a4f4d8a584. Report an issue: GitHub.