nocobase/nocobase · error · FlowSurfaceBadRequestError
flowSurfaces addBlock only supports registered block types/u
Error message
flowSurfaces addBlock only supports registered block types/uses
What it means
resolveBlockCatalogItem (catalog.ts:~4134) resolves addBlock requests by looking up input.type in BLOCK_CATALOG_BY_KEY or input.use in BLOCK_CATALOG_BY_USE. If neither lookup finds a registered item — the type/use is unknown, misspelled, or not part of the flowSurfaces block catalog — the server rejects the request because only registered block types/uses can be added.
Source
Thrown at packages/plugins/@nocobase/plugin-flow-engine/src/server/flow-surfaces/catalog.ts:4134
export function resolveSupportedBlockCatalogItem(
input: {
type?: string;
use?: string;
containerUse?: string;
},
options: {
context?: string;
enabledPackages?: ReadonlySet<string>;
requireCreateSupported?: boolean;
skipContainerValidation?: boolean;
} = {},
) {
const item =
(input.type ? BLOCK_CATALOG_BY_KEY.get(String(input.type).trim()) : undefined) ||
(input.use ? BLOCK_CATALOG_BY_USE.get(String(input.use).trim()) : undefined);
if (!item) {
throw new FlowSurfaceBadRequestError(`flowSurfaces addBlock only supports registered block types/uses`);
}
if (!isCatalogItemAvailable(item, options.enabledPackages)) {
throwUnavailableCatalogItem(item, {
context: options.context || 'addBlock',
requestedType: input.type,
requestedUse: input.use,
});
}
if (!options.skipContainerValidation && !isBlockAllowedInContainer(item, input.containerUse)) {
throw new FlowSurfaceBadRequestError(
`flowSurfaces addBlock '${input.type || input.use || item.key}' is not allowed under '${
input.containerUse || 'unknown'
}'`,
);
}
if (options.requireCreateSupported && item.createSupported === false) {
throw new FlowSurfaceBadRequestError(`flowSurfaces addBlock does not support creating '${item.key}' yet`);
}View on GitHub (pinned to fa42722fef)
Solutions
- Look up the exact registered block key/use in the flowSurfaces block catalog (BLOCK_CATALOG) and use it verbatim.
- Fix typos and casing in input.type or input.use.
- If the block comes from a plugin, enable that plugin so its items are registered in the catalog.
- If both fields are being dropped, verify the client actually sends type or use in the addBlock payload.
- After a version upgrade, refresh any stored configs referencing old block type names.
Example fix
// before
addBlock({ type: 'markdown ' /* unknown key */ });
// after
addBlock({ type: 'markdown' }); // exact registered block key, trimmed Defensive patterns
Strategy: type-guard
Validate before calling
// validate against the client-side copy of the block catalog before sending
const BLOCK_KEYS = new Set(['markdown', /* ...registered block keys */]);
function canAddBlock(input: { type?: string; use?: string }) {
return Boolean(input.type && BLOCK_KEYS.has(String(input.type).trim())) || Boolean(input.use && BLOCK_KEYS.has(String(input.use).trim()));
} Type guard
function isRegisteredBlockKey(k: string | undefined, catalog: ReadonlySet<string>): k is string {
return typeof k === 'string' && catalog.has(k.trim());
} Try / catch
try {
addBlockItem(input);
} catch (e) {
if (e instanceof FlowSurfaceBadRequestError && /only supports registered block types/.test(e.message)) {
// fetch the current block catalog and pick a valid type/use
const catalog = await getBlockCatalog();
console.error(`Unknown block type/use '${input.type || input.use}'. Valid:`, [...catalog].join(', '));
} else throw e;
} Prevention
- Source block type/use constants from the served catalog, never free-text strings.
- Trim and normalize keys exactly as the server does before sending.
- After flow-engine upgrades, re-validate stored block type names against the new catalog.
When it happens
Trigger: Calling the addBlock flowSurfaces operation with a type string not in the block catalog (typo, custom block never registered, casing mismatch) or with a use that no registered block declares; omitting both type and use so both lookups are undefined.
Common situations: Hand-written automation/API scripts using block names from a different NocoBase version's catalog; client code referencing a block contributed by a plugin that registers under a different use; renamed/removed block types after an upgrade; sending a raw collection name instead of a registered block type.
Related errors
- FLOW_SURFACE_BAD_REQUEST
- flowSurfaces field container '${containerUse}' is not suppor
- flowSurfaces field type 'jsColumn' is only allowed under tab
- flowSurfaces field type 'jsItem' is only allowed under form
- flowSurfaces field type 'divider' is only allowed under form
AI-assisted analysis of nocobase/nocobase@fa42722fef (2026-09-01).
Data as JSON: /api/errors/191d4d7e710ddd83.
Report an issue: GitHub.