{"record":{"id":"472404db3e9d3418","repo":"FlowiseAI/Flowise","slug":"workspace-id-is-required","errorCode":null,"errorMessage":"Workspace ID is required","messagePattern":"Workspace ID is required","errorType":"validation","errorClass":"InternalFlowiseError","httpStatus":412,"severity":"error","filePath":"packages/server/src/controllers/apikey/index.ts","lineNumber":83,"sourceCode":"                `Error: apikeyController.updateApiKey - permissions must be an array of strings!`\n            )\n        }\n        const user = req.user as LoggedInUser\n        const apiResponse = await apikeyService.updateApiKey(user, req.params.id, req.body.keyName, req.body.permissions)\n        return res.json(apiResponse)\n    } catch (error) {\n        next(error)\n    }\n}\n\n// Delete api key\nconst deleteApiKey = async (req: Request, res: Response, next: NextFunction) => {\n    try {\n        if (typeof req.params === 'undefined' || !req.params.id) {\n            throw new InternalFlowiseError(StatusCodes.PRECONDITION_FAILED, `Error: apikeyController.deleteApiKey - id not provided!`)\n        }\n        if (!req.user?.activeWorkspaceId) {\n            throw new InternalFlowiseError(StatusCodes.PRECONDITION_FAILED, `Workspace ID is required`)\n        }\n        const apiResponse = await apikeyService.deleteApiKey(req.params.id, req.user?.activeWorkspaceId)\n        return res.json(apiResponse)\n    } catch (error) {\n        next(error)\n    }\n}\n\n// Verify api key\nconst verifyApiKey = async (req: Request, res: Response, next: NextFunction) => {\n    try {\n        if (typeof req.params === 'undefined' || !req.params.apikey) {\n            throw new InternalFlowiseError(StatusCodes.PRECONDITION_FAILED, `Error: apikeyController.verifyApiKey - apikey not provided!`)\n        }\n        const apiResponse = await apikeyService.verifyApiKey(req.params.apikey)\n        return res.json(apiResponse)\n    } catch (error) {\n        next(error)","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/FlowiseAI/Flowise/blob/abe4a8601a058047b350c260676826e21dd14101/packages/server/src/controllers/apikey/index.ts#L65-L101","documentation":"Thrown by deleteApiKey after the id guard passes, when req.user?.activeWorkspaceId is falsy. Unusually for a workspace check in this codebase it uses HTTP 412 (PRECONDITION_FAILED) with the bare message 'Workspace ID is required' (no controller prefix), whereas the assistants and chat-messages controllers throw 404 NOT_FOUND for the same condition. The active workspace id is attached to req.user by the auth/session middleware from the JWT/session; if that claim is absent the delete cannot be scoped to a workspace and is rejected.","triggerScenarios":"Authenticated DELETE /api/v1/apikey/<id> where the session/JWT carries no activeWorkspaceId — the user has no active workspace selected, the auth middleware did not populate req.user.activeWorkspaceId, or the user has no workspace membership.","commonSituations":"Newly provisioned user who never completed workspace selection/creation; JWT minted without the workspace claim; auth middleware misconfigured or bypassed in a custom deployment; the user's workspace membership was deleted from the DB while their session remained valid.","solutions":["Have the client select/switch to an active workspace first (the workspace switch endpoint) so the session carries activeWorkspaceId, then retry the delete.","Verify the auth middleware populates req.user (including activeWorkspaceId) from the token before this router runs.","Confirm the user record actually has a workspace membership in the database; recreate the membership if it was removed.","Note the status-code inconsistency (412 here vs 404 elsewhere) if you centralize error handling on status."],"exampleFix":"// before: delete attempted before a workspace is selected\nawait fetch(`${BASE}/api/v1/apikey/${id}`, { method: 'DELETE', headers })\n\n// after: ensure an active workspace is set in the session first\nawait selectWorkspace(activeWorkspaceId) // sets activeWorkspaceId claim in session/JWT\nawait fetch(`${BASE}/api/v1/apikey/${id}`, { method: 'DELETE', headers })","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"// If the client tracks the logged-in user shape:\nconst hasActiveWorkspace = (u: unknown): u is { activeWorkspaceId: string } =>\n  !!u && typeof u === 'object' &&\n  typeof (u as any).activeWorkspaceId === 'string' &&\n  (u as any).activeWorkspaceId.length > 0","tryCatchPattern":"try {\n  await deleteApiKey(id)\n} catch (err) {\n  // 412 'Workspace ID is required' (or 404 'workspace' elsewhere)\n  if (err?.statusCode === 412 && /workspace id is required/i.test(err.message)) {\n    await selectWorkspace() // re-establish activeWorkspaceId in the session\n    return deleteApiKey(id) // retry once\n  }\n  throw err\n}","preventionTips":["Drive all authenticated calls through a client that ensures a workspace is selected first.","On startup, fetch the user profile and require activeWorkspaceId before enabling destructive actions.","Handle 412/404 workspace-or-org errors uniformly by re-running workspace/org selection and retrying once."],"tags":["authentication","session","workspace","precondition-failed","express","flowise","apikey"],"backgroundTag":null,"analyzedSha":"abe4a8601a058047b350c260676826e21dd14101","analyzedAt":"2026-08-12T16:04:40.823Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}