ruvnet/ruflo · error · TypeError
selectAgentBackend: pod must be a validated PodTemplate obje
Error message
selectAgentBackend: pod must be a validated PodTemplate object
What it means
Defensive TypeError at the top of selectAgentBackend(). Fires when the pod argument is null or not an object at all (string, number, undefined). The function's JSDoc states validation is the caller's responsibility and expects a PodTemplate already passed through validatePodTemplate(). This guard catches the case where a caller skipped validation entirely and passed a raw JSON string, null, or undefined.
Source
Thrown at v3/@claude-flow/cli/src/business-pods/domain-affinity-policy.ts:53
/** Structured routing decision. `reason` is rendered into the routing
* rationale via `hooks_explain` so operators can see why each pod was
* routed where it was. */
export interface BackendDecision {
backend: AgentBackend;
reason: string;
}
/**
* Decide which backend `@metaharness/router` should prefer for a pod tick.
*
* @param pod A validated PodTemplate. Validation is the caller's
* responsibility; this function will throw on malformed input
* (specifically on missing `preferLocalExecution` or
* `budgetUsdMonthly`).
*/
export function selectAgentBackend(pod: PodTemplate): BackendDecision {
if (pod === null || typeof pod !== 'object') {
throw new TypeError('selectAgentBackend: pod must be a validated PodTemplate object');
}
if (typeof pod.preferLocalExecution !== 'boolean') {
throw new TypeError(
'selectAgentBackend: pod.preferLocalExecution must be boolean (validate via pod-schema first)',
);
}
if (typeof pod.budgetUsdMonthly !== 'number' || !Number.isFinite(pod.budgetUsdMonthly)) {
throw new TypeError(
'selectAgentBackend: pod.budgetUsdMonthly must be a finite number (validate via pod-schema first)',
);
}
if (pod.preferLocalExecution) {
return {
backend: 'local-stdio',
reason: `pod "${pod.name}" preferLocalExecution=true — domain-affinity policy pins to local stdio`,
};
}View on GitHub (pinned to 6b01dc5a68)
Solutions
- Always run the pod through validatePodTemplate() before calling selectAgentBackend() — it returns a typed PodTemplate or throws PodTemplateValidationError
- Null-check the result of any loader/lookup before passing it to selectAgentBackend()
Example fix
// before: const raw = fs.readFileSync(path, 'utf8'); const decision = selectAgentBackend(raw); // string, throws TypeError // after: const pod = validatePodTemplate(JSON.parse(fs.readFileSync(path, 'utf8'))); const decision = selectAgentBackend(pod);
Defensive patterns
Strategy: validation
Validate before calling
import { validatePodTemplate, type PodTemplate } from '@claude-flow/cli/business-pods/pod-schema';
// Always validate the raw JSON first — validatePodTemplate returns a typed
// PodTemplate or throws PodTemplateValidationError. Passing the result to
// selectAgentBackend guarantees the object-shape guard never fires.
const pod: PodTemplate = validatePodTemplate(JSON.parse(rawJsonString));
const decision = selectAgentBackend(pod); Type guard
import type { PodTemplate } from '@claude-flow/cli/business-pods/pod-schema';
function isPodTemplate(v: unknown): v is PodTemplate {
return v !== null && typeof v === 'object'
&& typeof (v as PodTemplate).preferLocalExecution === 'boolean'
&& typeof (v as PodTemplate).budgetUsdMonthly === 'number';
} Prevention
- Always run validatePodTemplate() on any externally loaded pod JSON before passing it to routing or execution
- Never pass the raw output of fs.readFileSync or a failed Map.get() to selectAgentBackend
When it happens
Trigger: Calling selectAgentBackend(pod) where pod is null, undefined, a string, a number, or any non-object primitive. Happens when a caller reads a pod template JSON file but passes the raw string, or passes undefined from a failed lookup, before validating.
Common situations: A pod loader returned undefined (file not found) and the caller forwarded it without checking; a JSON.parse result was passed directly without validation; a Map.get() returned undefined for a missing key.
Related errors
- selectAgentBackend: pod.preferLocalExecution must be boolean
- selectAgentBackend: pod.budgetUsdMonthly must be a finite nu
- pod-template at ${path}: field "${key}" must be a non-empty
- pod-template at ${path}: field "${key}" must be a finite num
- pod-template at ${path}: field "${key}" must be a boolean
AI-assisted analysis of ruvnet/ruflo@6b01dc5a68 (2026-08-12).
Data as JSON: /api/errors/42933e78e4b8d70c.
Report an issue: GitHub.