{"record":{"id":"b627c64ae51c46b0","repo":"nocobase/nocobase","slug":"flowsurfaces-addaction-only-supports-registered-ac","errorCode":null,"errorMessage":"flowSurfaces addAction only supports registered action types/uses","messagePattern":"flowSurfaces addAction only supports registered action types/uses","errorType":"validation","errorClass":"FlowSurfaceBadRequestError","httpStatus":400,"severity":"error","filePath":"packages/plugins/@nocobase/plugin-flow-engine/src/server/flow-surfaces/catalog.ts","lineNumber":4240,"sourceCode":"        requestedType,\n      });\n    }\n    if (matchedAll.length && !matched.length) {\n      throwUnavailableCatalogItem(matchedAll[0], {\n        context: options.context || 'addAction',\n        requestedType,\n      });\n    }\n    if (matched.length > 1 && !input.containerUse) {\n      throw new FlowSurfaceBadRequestError(\n        `flowSurfaces addAction type '${requestedType}' requires containerUse to resolve a public action capability`,\n      );\n    }\n    item = matched[0];\n  }\n\n  if (!item) {\n    throw new FlowSurfaceBadRequestError(`flowSurfaces addAction only supports registered action types/uses`);\n  }\n  if (!isCatalogItemAvailable(item, options.enabledPackages)) {\n    throwUnavailableCatalogItem(item, {\n      context: options.context || 'addAction',\n      requestedType: input.type,\n      requestedUse: input.use,\n    });\n  }\n  if (requestedType) {\n    const publicKey = toPublicActionCatalogItem(item).key;\n    if (requestedType !== publicKey) {\n      throw new FlowSurfaceBadRequestError(\n        `flowSurfaces addAction only supports public action type '${publicKey}' under '${\n          input.containerUse || 'unknown'\n        }'`,\n      );\n    }\n  }","sourceCodeStart":4222,"sourceCodeEnd":4258,"githubUrl":"https://github.com/nocobase/nocobase/blob/fa42722fefe44265490dff2c27d79e2882bce4fa/packages/plugins/@nocobase/plugin-flow-engine/src/server/flow-surfaces/catalog.ts#L4222-L4258","documentation":"This is the fallback guard of resolveSupportedActionCatalogItem: after trying the `use` branch and the `type` branch, if neither produced a catalog item (both input.type and input.use were empty/blank, or lookups matched nothing outside the earlier checks), the resolver rejects the request because only registered action types/uses are supported by flowSurfaces addAction.","triggerScenarios":"flowSurfaces addAction called with neither type nor use (or only whitespace), or with values absent from ACTION_CATALOG_BY_KEY / ACTION_CATALOG_BY_USE such that `item` stays undefined.","commonSituations":"Client sends an empty payload due to a form that did not bind the action selector; typo'd or custom action key that was never registered; plugin providing the action is not registered in the catalog at all (distinct from being disabled, which throws a different 'unavailable' error).","solutions":["Ensure the request includes a valid `type` (public action key) or `use` registered in the action catalog","List the action catalog (e.g. via the flowSurfaces catalog endpoints) to confirm the exact key/use spelling","Register the custom action in ACTION_CATALOG if it is a new capability","Fix the client payload so the action selector value is actually submitted"],"exampleFix":"// before\nawait flowSurfaces.addAction({ containerUse: 'table' }); // no type/use -> throws\n// after\nawait flowSurfaces.addAction({ type: 'customize:popup', containerUse: 'table' });","handlingStrategy":"validation","validationCode":"const type = String(input.type || '').trim();\nconst use = String(input.use || '').trim();\nif (!type && !use) throw new Error('addAction requires a registered action type or use');\nif (type && !ACTION_CATALOG_BY_KEY.has(type) && !(ACTION_CATALOG_BY_USE.get(use) || []).length) {\n  throw new Error(`Action '${type || use}' is not registered`);\n}","typeGuard":"function isRegisteredAction(input) {\n  const t = String(input?.type || '').trim();\n  const u = String(input?.use || '').trim();\n  return Boolean((t && ACTION_CATALOG_BY_KEY.has(t)) || (u && (ACTION_CATALOG_BY_USE.get(u) || []).length));\n}","tryCatchPattern":"try {\n  await flowSurfaces.addAction(input);\n} catch (e) {\n  if (e instanceof FlowSurfaceBadRequestError && /only supports registered action types\\/uses/.test(e.message)) {\n    // surface catalog choices to the user instead of submitting\n  } else throw e;\n}","preventionTips":["Never submit addAction with empty type and use","Validate keys against the action catalog before calling","Register custom actions before referencing them"],"tags":["validation","catalog","bad-request"],"backgroundTag":"unregistered-action-type","analyzedSha":"fa42722fefe44265490dff2c27d79e2882bce4fa","analyzedAt":"2026-09-01T00:54:31.202Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}