hcengineering/platform · error · Error

User is not signed in

Error message

User is not signed in

What it means

getTarget resolves a platform User (email+workspace) to the stored UserRecord and workspace worker. If no record matches the email in that workspace, it throws 'User is not signed in' — the telegram integration only serves users who completed registration.

Source

Thrown at services/telegram/pod-telegram/src/platform.ts:54

      wsWorker = await WorkspaceWorker.create(
        this.ctx,
        this.storageAdapter,
        workspace,
        userStorage,
        lastMsgStorage,
        channelStorage
      )
      this.clientMap.set(workspace, wsWorker)
    }

    await wsWorker.addUser(tgUser)
  }

  async getTarget ({ workspace, email }: User): Promise<[UserRecord, WorkspaceWorker | undefined]> {
    const res = await this.storage.findOne({ email, workspace })

    if (res === null) {
      throw Error('User is not signed in')
    }

    return [res, this.clientMap.get(workspace)]
  }

  async removeUser (user: User): Promise<void> {
    const [res, wsWorker] = await this.getTarget(user)

    if (wsWorker === undefined) {
      throw Error(`Invalid workspace: '${user.workspace}'`)
    }

    await wsWorker.removeUser({ phone: res.phone })
  }

  async getUserRecord ({ workspace, phone }: Pick<TgUser, 'workspace' | 'phone'>): Promise<UserRecord | undefined> {
    return (await this.storage.findOne({ phone, workspace })) ?? undefined
  }

View on GitHub (pinned to 63e28dc964)

Solutions

  1. Ensure the user completed signup (addUser) for the exact workspace before targeting them.
  2. Verify the email and workspace fields match the stored record (case/whitespace).
  3. Handle the error upstream: skip the notification or prompt the user to reconnect the telegram integration.
  4. If the user re-registered with a new email, update subscriptions to the new identity.

Example fix

// before
const [user, worker] = await platform.getTarget(user)
// after
try {
  const [user, worker] = await platform.getTarget(user)
} catch (err) {
  if (err.message === 'User is not signed in') {
    console.warn('Skipping telegram delivery: user not signed in', user.email)
    return
  }
  throw err
}
Defensive patterns

Strategy: try-catch

Validate before calling

const signedIn = await storage.findOne({ email: user.email, workspace: user.workspace })
if (signedIn === null) console.warn(`${user.email} has no telegram registration; getTarget will throw`)

Type guard

function isRegistered(record: UserRecord | null): record is UserRecord { return record !== null }

Try / catch

try {
  const [record, worker] = await platform.getTarget(user)
} catch (err) {
  if (err.message === 'User is not signed in') {
    console.warn('Telegram delivery skipped: user not signed in', user.email)
    return // skip notification gracefully
  }
  throw err
}

Prevention

When it happens

Trigger: Calling getTarget (from res/wsWorker message handling) with a User whose email has no stored record: the user never registered via the bot, registered in a different workspace, or their record was removed (removeUser/logout) while notifications still target them.

Common situations: Sending notifications to a user who signed out of the telegram integration, an email changed upstream but not re-registered, a wrong workspace id in the User payload, or storage cleared without revoking subscriptions.

Related errors


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