actualbudget/actual · error
InitialFocus expects a single valid React element as its chi
Error message
InitialFocus expects a single valid React element as its child.
What it means
InitialFocus is a React wrapper that clones its single child and attaches a ref so the element receives focus on mount. It uses Children.only, so it throws if children is not exactly one valid React element.
Source
Thrown at packages/component-library/src/InitialFocus.ts:60
ref.current instanceof HTMLInputElement ||
ref.current instanceof HTMLTextAreaElement
) {
ref.current.setSelectionRange(0, 10000);
}
}
}, 0);
}
}, []);
if (typeof children === 'function') {
return children(ref);
}
const child = Children.only(children);
if (isValidElement(child)) {
return cloneElement(child, { ref });
}
throw new Error(
'InitialFocus expects a single valid React element as its child.',
);
}
View on GitHub (pinned to d4334cb6e6)
Solutions
- Ensure InitialFocus has exactly one element child.
- Wrap multiple children in a single element and put InitialFocus around the element that should receive focus.
- Move conditional rendering outside so a valid element is always passed, or conditionally render InitialFocus itself.
Example fix
// before
<InitialFocus>{cond && <Input />}</InitialFocus>
// after
{cond && <InitialFocus><Input /></InitialFocus>} Defensive patterns
Strategy: validation
Validate before calling
import { Children, isValidElement } from 'react';
const child = Children.only(children);
if (!isValidElement(child)) {
throw new Error('InitialFocus requires exactly one valid element child');
} Type guard
import { Children, isValidElement, type ReactElement } from 'react';
function isSingleElement(children: React.ReactNode): children is ReactElement {
const child = Children.only(children);
return isValidElement(child);
} Try / catch
try {
return <InitialFocus>{child}</InitialFocus>;
} catch (err) {
console.error('InitialFocus misuse:', (err as Error).message);
return child;
} Prevention
- Always give InitialFocus exactly one element child.
- Never place conditional expressions ({cond && <Input/>}) directly inside InitialFocus.
- Focus the wrapper on the specific input that needs autofocus, not a container.
- Add a unit test rendering each usage of InitialFocus to catch refactors adding children.
When it happens
Trigger: Rendering <InitialFocus> with zero children, multiple children, a string, a fragment of multiple elements, or a conditional returning null/false.
Common situations: Adding a second input inside InitialFocus during refactoring; JSX like <InitialFocus>{condition && <Input/>}</InitialFocus> where condition is false; passing text content instead of an element.
Related errors
- Unrecognized sync source: ${String(syncSource)}
- Invalid --name: must be a non-empty string.
- No update fields provided. Use --name or --offbudget.
- Invalid cutoff date: expected a valid date (e.g. YYYY-MM-DD)
- No update fields provided. Use --name or --hidden.
AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29).
Data as JSON: /api/errors/cd829b06fbb71812.
Report an issue: GitHub.