actualbudget/actual · error · TypeError
UUID format no longer matches expected format
Error message
UUID format no longer matches expected format
What it means
generateGroupId creates a sync GroupId via uuidv4() and then re-validates it with isValidGroupId (a guard against the UUID format changing across library upgrades). If the generated UUID no longer matches the expected format, it throws a TypeError 'UUID format no longer matches expected format'. This is a defensive invariant check, essentially unreachable in normal operation.
Source
Thrown at packages/sync-server/src/app-sync.ts:73
express.raw({
type: 'application/encrypted-file',
limit: `${config.get('upload.syncEncryptedFileSizeLimitMB')}mb`,
}),
);
app.use(express.json({ limit: `${config.get('upload.fileSizeLimitMB')}mb` }));
export { app as handlers };
const OK_RESPONSE = { status: 'ok' };
function boolToInt(deleted: boolean) {
return deleted ? 1 : 0;
}
function generateGroupId(): GroupId {
const id = uuidv4();
if (!isValidGroupId(id)) {
throw new TypeError('UUID format no longer matches expected format');
}
return id;
}
function extractSingleHeader(
req: Request,
res: Response,
key: string,
): string | null {
const value = req.headers[key];
if (!value) {
return null;
}
if (typeof value !== 'string') {
res.status(400).send('Duplicate headers encountered for key ' + key);
return null;
}
return value;View on GitHub (pinned to d4334cb6e6)
Solutions
- Check the installed uuid package version/implementation and restore standard v4 output (lowercase 8-4-4-4-12).
- If uuidv4 is mocked in tests, make the mock return a valid v4 UUID string.
- Inspect isValidGroupId and update it only if the ID format intentionally changed across the codebase.
- Reinstall dependencies (yarn install) to rule out a corrupted/pinned wrong uuid version.
Example fix
// before
vi.mock('uuid', () => ({ v4: () => 'test-id' }));
// after
vi.mock('uuid', () => ({ v4: () => '0b9e6b1e-7a4c-4f3e-9d2a-1c8b5f6e7a90' })); Defensive patterns
Strategy: type-guard
Validate before calling
function isValidGroupId(id: string): boolean {
return /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/.test(id);
}
const id = uuidv4();
if (!isValidGroupId(id)) throw new TypeError('uuid source produced invalid v4 id'); Type guard
function isUuidV4(value: string): value is `${string}-${string}-${string}-${string}-${string}` {
return /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/.test(value);
} Prevention
- Never mock uuidv4 with non-UUID strings in tests.
- Keep the uuid package on a standard v4 implementation across upgrades.
- Treat this throw as an invariant violation: fix the uuid source, not the guard.
When it happens
Trigger: Only when uuidv4() returns a value that fails isValidGroupId — practically meaning the uuid library was swapped/upgraded to produce a different format (e.g. non-lowercase or braced UUIDs) or mocked to return non-UUID values.
Common situations: Dependency upgrade or replacement of the uuid package; test mocks stubbing uuidv4 with values like 'mock-id'; custom crypto.randomUUID polyfills returning a different casing/format.
Related errors
- Sync ID is required for sync ${flag}. Set --sync-id or ACTUA
- Could not resolve on-disk budget id for syncId ${syncId} aft
- TrieNode for key ${k} could not be found
- Timestamp.InvalidError: ${data.timestamp}
- Timestamp.ClockDriftError
AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29).
Data as JSON: /api/errors/7f8c24a013979199.
Report an issue: GitHub.