ruvnet/ruflo · error
Invalid registry: missing version
Error message
Invalid registry: missing version
What it means
deserializeRegistry() JSON.parses a serialized PatternRegistry and validates that the parsed object has a truthy top-level `version` field before casting it to PatternRegistry. A payload that parses as valid JSON but lacks `version` — `{}`, a CFP pattern document, a truncated/hand-edited file, or data from an incompatible schema — is rejected. Note JSON.parse errors (malformed JSON) throw separately before this check runs.
Source
Thrown at v3/@claude-flow/cli/src/transfer/store/registry.ts:245
return updated;
}
/**
* Serialize registry to JSON
*/
export function serializeRegistry(registry: PatternRegistry): string {
return JSON.stringify(registry, null, 2);
}
/**
* Deserialize registry from JSON
*/
export function deserializeRegistry(json: string): PatternRegistry {
const registry = JSON.parse(json);
// Validate version
if (!registry.version) {
throw new Error('Invalid registry: missing version');
}
return registry as PatternRegistry;
}
/**
* Sign registry with private key
*/
export function signRegistry(registry: PatternRegistry, privateKey: string): PatternRegistry {
const content = JSON.stringify({
version: registry.version,
updatedAt: registry.updatedAt,
patterns: registry.patterns.map(p => p.cid),
totalPatterns: registry.totalPatterns,
});
// In production: Use actual Ed25519 signing
const signature = cryptoView on GitHub (pinned to fa13ee4ad6)
Solutions
- Open the JSON and confirm it is a registry document: it needs a top-level `"version"` alongside `"patterns"`/`"updatedAt"` — if it looks like a single pattern, you are passing the wrong file.
- Delete the corrupt/cached registry file and re-download it from the registry source (re-run store.initialize() or the discovery step).
- If you generate registries yourself, always include the version field (use serializeRegistry() to write, never hand-rolled JSON.stringify of a partial object).
- If the file came from an older tool version, regenerate it with the current version rather than hand-patching.
Example fix
// before
const registry = deserializeRegistry(await readFile('cache/registry.json', 'utf8'));
// cache/registry.json = { "patterns": [] } → throws: Invalid registry: missing version
// after
await rm('cache/registry.json'); // drop the bad cache
const ok = await store.initialize(); // re-download a proper registry
if (!ok) throw new Error('registry re-fetch failed'); Defensive patterns
Strategy: type-guard
Validate before calling
import { readFile } from 'node:fs/promises';
const text = await readFile(registryPath, 'utf8');
const parsed: unknown = JSON.parse(text); // malformed JSON throws here, separately
if (!isPatternRegistryLike(parsed)) {
await rm(registryPath); // drop the bad cache and let discovery re-download
throw new Error('registry cache was invalid — removed; re-run initialize()');
} Type guard
function isPatternRegistryLike(v: unknown): v is { version: string; patterns: unknown[] } {
return typeof v === 'object' && v !== null &&
typeof (v as { version?: unknown }).version === 'string' && (v as { version?: unknown }).version.length > 0 &&
Array.isArray((v as { patterns?: unknown }).patterns);
} Try / catch
try {
const registry = deserializeRegistry(json);
} catch (err) {
if (err instanceof SyntaxError) throw new Error('registry file is not valid JSON — re-download it');
if (err instanceof Error && err.message === 'Invalid registry: missing version') {
throw new Error('wrong or outdated registry file — expected a serialized PatternRegistry with a version field');
}
throw err;
} Prevention
- Write registries only with serializeRegistry() so the version field can never be omitted
- Distinguish file kinds by naming (registry.json vs pattern.cfp.json) so the two never get swapped
- Never hand-edit cached registry files; delete and re-download instead
- When accepting registries from other tools, run the type guard before deserializeRegistry()
When it happens
Trigger: (1) Feeding a pattern (CFP) file into a code path expecting a registry file; (2) a cached registry.json edited by hand or truncated by a crashed writer; (3) an empty object or different-schema JSON (e.g. `{ patterns: [] }` written without version); (4) version field present but empty string/falsy.
Common situations: Two file formats (registry vs pattern) sharing .json extension and getting swapped; scripts generating registry files that forgot the version key; partial downloads cached to disk; schema drift between the tool version that wrote the file and the one reading it.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- pod-template must be a JSON object
- Routes config must be a flat array of routes
- Invalid route entry: ${JSON.stringify(r)}
- Duplicate route name: ${r.name}
- RVFA header failed validation
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/33c8ae4f3adaad9f.
Report an issue: GitHub.