{"record":{"id":"07e31504329f4ade","repo":"multica-ai/multica","slug":"binding-token-invalid-or-expired","errorCode":null,"errorMessage":"binding token invalid or expired","messagePattern":"binding token invalid or expired","errorType":"exception","errorClass":"ErrBindingTokenInvalid","httpStatus":410,"severity":"error","filePath":"server/internal/integrations/lark/binding_token.go","lineNumber":273,"sourceCode":"\t\tInstallationID: p.InstallationID,\n\t\tChannelUserID:  string(p.LarkOpenID),\n\t})\n\tif err != nil {\n\t\tif errors.Is(err, pgx.ErrNoRows) {\n\t\t\treturn ErrBindingAlreadyAssigned\n\t\t}\n\t\treturn fmt.Errorf(\"bind installer: %w\", err)\n\t}\n\treturn nil\n}\n\n// ErrBindingTokenInvalid is returned by RedeemAndBind when the token\n// hash does not exist, the token has already been consumed, or it\n// has expired. The caller must NOT distinguish those sub-cases —\n// that distinction enables timing oracles for token replay races and\n// adds no product value (the user sees the same \"link invalid or\n// expired, please request a new one\" copy either way).\nvar ErrBindingTokenInvalid = errors.New(\"binding token invalid or expired\")\n\n// ErrBindingAlreadyAssigned is returned by RedeemAndBind when a\n// lark_user_binding row already exists for the (installation,\n// open_id) pair and points at a different Multica user. Account\n// transfer must go through an explicit unbind flow; a binding token\n// cannot be used to grab an already-bound open_id from another user.\nvar ErrBindingAlreadyAssigned = errors.New(\"lark open_id is already bound to a different user\")\n\n// ErrBindingNotWorkspaceMember is returned by RedeemAndBind and\n// BindInstallerTx when the user is not (or no longer) a member of the\n// target workspace, detected by an explicit IsWorkspaceMember check\n// (MUL-3515 §4 removed the member FK that used to enforce this).\n// Translated to 403 at the HTTP boundary.\nvar ErrBindingNotWorkspaceMember = errors.New(\"redeemer is not a workspace member\")\n\nfunc randomToken(n int) (string, error) {\n\tbuf := make([]byte, n)\n\tif _, err := rand.Read(buf); err != nil {","sourceCodeStart":255,"sourceCodeEnd":291,"githubUrl":"https://github.com/multica-ai/multica/blob/2c0912b6ec764b373d44eeea1e80f0d9f11ab417/server/internal/integrations/lark/binding_token.go#L255-L291","documentation":"Error \"binding token invalid or expired\" thrown in multica-ai/multica.","triggerScenarios":"Thrown at server/internal/integrations/lark/binding_token.go:273 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Request a new binding token and redeem it before it expires."],"exampleFix":null,"handlingStrategy":null,"validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"2c0912b6ec764b373d44eeea1e80f0d9f11ab417","analyzedAt":"2026-08-15T13:25:18.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}