mastra-ai/mastra · error · Error
useJSONSchemaForm must be used within a JSONSchemaForm.Root
Error message
useJSONSchemaForm must be used within a JSONSchemaForm.Root
What it means
useJSONSchemaForm returns the shared form state (addField, fields, updateField, maxDepth, etc.) from JSONSchemaFormContext, which only JSONSchemaForm.Root provides. Outside a Root the context is null and the hook throws, guaranteeing form subcomponents always have valid form state.
Source
Thrown at packages/playground-ui/src/ds/components/JSONSchemaForm/json-schema-form-context.tsx:27
maxDepth: number;
}
const JSONSchemaFormContext = React.createContext<JSONSchemaFormContextValue | null>(null);
export function JSONSchemaFormProvider({
children,
value,
}: {
children: React.ReactNode;
value: JSONSchemaFormContextValue;
}) {
return <JSONSchemaFormContext.Provider value={value}>{children}</JSONSchemaFormContext.Provider>;
}
export function useJSONSchemaForm(): JSONSchemaFormContextValue {
const context = React.useContext(JSONSchemaFormContext);
if (!context) {
throw new Error('useJSONSchemaForm must be used within a JSONSchemaForm.Root');
}
return context;
}
View on GitHub (pinned to 75dd419e61)
Solutions
- Move the consumer inside <JSONSchemaForm.Root schema={...}>...</JSONSchemaForm.Root>.
- If the UI must live outside the Root element, lift the Root higher so the whole form subtree is covered, or pass the needed callbacks as explicit props instead of using the hook.
- For modals/portals, render them within Root's subtree (React context crosses portals, but not tree boundaries — keep Root as an ancestor).
- Add a useMaybeJSONSchemaForm-style nullable accessor if optional usage is a real requirement.
Example fix
// before
<AddFieldButton /> // outside Root
// after
<JSONSchemaForm.Root schema={schema} onSubmit={submit}>
<AddFieldButton />
</JSONSchemaForm.Root> Defensive patterns
Strategy: try-catch
Validate before calling
// Ensure JSONSchemaForm.Root wraps all consumers of useJSONSchemaForm.
// Optional access pattern:
const ctx = React.useContext(JSONSchemaFormContext);
if (!ctx) console.warn('useJSONSchemaForm consumer must be nested in JSONSchemaForm.Root'); Type guard
function hasFormContext(c: JSONSchemaFormContextValue | null): c is JSONSchemaFormContextValue {
return c !== null;
} Try / catch
// Hooks cannot be try/catch-wrapped; use an error boundary at the form section level:
<ErrorBoundary fallback={<InvalidFormUsage /> }>
<MyAddFieldButton />
</ErrorBoundary> Prevention
- Nest all form chrome (toolbars, field lists) inside JSONSchemaForm.Root.
- Pass addField/updateField as explicit props when a control must live outside the form tree.
- Render modals/portals as descendants of Root so context still flows.
- Differentiate Root-level (useJSONSchemaForm) vs Field-level (useJSONSchemaFormField) hooks when choosing which to call.
When it happens
Trigger: Calling useJSONSchemaForm in a component rendered outside <JSONSchemaForm.Root> — e.g. a custom add-field button or field list placed outside the Root, or a child lifted into a separate tree (portal/modal without its own Root).
Common situations: Building custom form chrome (toolbar, add field button) and forgetting to place it inside Root; rendering the form's field list in a parent component for layout reasons; storybook examples mounting subcomponents in isolation.
Related errors
- useJSONSchemaFormField must be used within a JSONSchemaForm.
- Comment compounds must be rendered within Comment
- ${componentName} must be used within EnvironmentVariablesEdi
- useMainSidebar must be used within a MainSidebarProvider.
- useMobileDrawer must be used within a MainSidebarProvider.
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/445b293653a324f2.
Report an issue: GitHub.