actualbudget/actual · error
ServerContext not initialized
Error message
ServerContext not initialized
What it means
ServerContext is a React context exposing server connection info (url, version, multiuserEnabled, loginMethods). Its createContext default object contains deliberately-throwing stubs so that calls made before the provider mounts fail loudly instead of silently doing nothing. `setURL` rejects with this error because the default provider has never replaced the stub.
Source
Thrown at packages/desktop-client/src/components/ServerContext.tsx:48
setURL: (
url: string,
opts?: { validate?: boolean },
) => Promise<{ error?: string }>;
refreshLoginMethods: () => Promise<void>;
setMultiuserEnabled: (enabled: boolean) => void;
setLoginMethods: (methods: LoginMethod[]) => void;
};
const ServerContext = createContext<ServerContextValue>({
url: null,
version: '',
multiuserEnabled: false,
availableLoginMethods: [],
setURL: () => Promise.reject(new Error('ServerContext not initialized')),
refreshLoginMethods: () =>
Promise.reject(new Error('ServerContext not initialized')),
setMultiuserEnabled: () => {
throw new Error('ServerContext not initialized');
},
setLoginMethods: () => {
throw new Error('ServerContext not initialized');
},
});
export const useServerURL = () => useContext(ServerContext).url;
export const useServerVersion = () => useContext(ServerContext).version;
export const useSetServerURL = () => useContext(ServerContext).setURL;
export const useMultiuserEnabled = () => {
const { multiuserEnabled } = useContext(ServerContext);
const loginMethod = useLoginMethod();
return multiuserEnabled && loginMethod === 'openid';
};
export const useLoginMethod = () => {
const availableLoginMethods = useContext(ServerContext).availableLoginMethods;
View on GitHub (pinned to d4334cb6e6)
Solutions
- Wrap the component (or test render) in the ServerProvider from packages/desktop-client/src/components/ServerContext.tsx so the real implementation replaces the default stubs.
- In tests, render with the app's standard test wrapper/helper that already includes ServerProvider (or mock the context value with a vi.fn resolving instead of rejecting).
- Verify the hook is consumed below the provider — move the component into the provider subtree rather than calling context methods at module scope.
Example fix
// before (test)
render(<ServerSettings />);
// after
render(
<ServerProvider>
<ServerSettings />
</ServerProvider>
); Defensive patterns
Strategy: try-catch
Validate before calling
const ctx = useContext(ServerContext);
const isInitialized = ctx.url !== undefined && typeof ctx.setURL === 'function' && !String(ctx.setURL).includes('not initialized');
if (!isInitialized) throw new Error('ServerProvider missing — wrap component in <ServerProvider>'); Type guard
function hasServerContext(ctx): ctx is ServerContextValue & { setURL: (url: string) => Promise<void> } {
return typeof ctx?.setURL === 'function' && ctx.url != null;
} Try / catch
try {
await setURL(newUrl);
} catch (e) {
if (e.message.includes('ServerContext not initialized')) {
// provider missing: skip persisting or fall back to local state
} else throw e;
} Prevention
- Always render server-dependent components inside ServerProvider, including test/story renders.
- Use the app's shared test wrapper so the provider is never forgotten.
- Never destructure context methods at module scope; call them inside components under the provider.
When it happens
Trigger: Calling `useSetServerURL()(...)` (or consuming ServerContext.setURL directly) in a component rendered OUTSIDE the <ServerProvider> tree, or during a window where the provider hasn't mounted (e.g. in tests rendering the component in isolation).
Common situations: Unit tests rendering a component with React Testing Library without wrapping it in ServerProvider; storybook stories rendering a settings page standalone; a code change moving a component outside the provider in the component tree; calling setURL before the app bootstraps the provider.
Related errors
- Unitialised context method called: onBudgetAction
- Unitialised context method called: onToggleSummaryCollapse
- useAuth must be used within an AuthProvider
- InitialFocus expects a single valid React element as its chi
- Unknown budget action type: ${String(type)}
AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29).
Data as JSON: /api/errors/9fc52191ad017497.
Report an issue: GitHub.