ruvnet/ruflo · error

SemanticRouter requires a dimension in config

Error message

SemanticRouter requires a dimension in config

What it means

The SemanticRouter constructor requires config.dimension to be a number (it sizes every embedding it will store — addIntentWithEmbeddings later enforces Float32Array of exactly this length). A missing, undefined, or non-numeric dimension throws immediately at construction.

Solutions

  1. Pass dimension matching your embedding model: 384 (all-MiniLM-L6-v2), 768 (bge-base), 1536 (text-embedding-3-small), 3072 (text-embedding-3-large), etc.
  2. Parse/validate config at load time: Number.isFinite(config.dimension) before constructing
  3. Centralize the dimension in one constant shared by the embedder and the router so they cannot diverge
  4. If config is dynamic, default it explicitly (e.g., ?? 384) rather than leaving it undefined

Example fix

// before
const router = new SemanticRouter({ metric: 'cosine' } as any); // throws: requires a dimension
// after
const DIM = 384; // all-MiniLM-L6-v2
const router = new SemanticRouter({ dimension: DIM, metric: 'cosine' });
Defensive patterns

Strategy: validation

Validate before calling

function makeRouter(cfg: unknown) {
  const dimension = Number((cfg as any)?.dimension);
  if (!Number.isFinite(dimension) || dimension <= 0) {
    throw new Error('SemanticRouter config needs numeric dimension (e.g., 384 for MiniLM)');
  }
  return new SemanticRouter({ dimension, metric: 'cosine' });
}

Type guard

function hasNumericDimension(cfg: unknown): cfg is { dimension: number } {
  return !!cfg && typeof (cfg as any).dimension === 'number' && Number.isFinite((cfg as any).dimension);
}

Try / catch

try {
  router = new SemanticRouter(config as any);
} catch (e) {
  if (e instanceof Error && e.message === 'SemanticRouter requires a dimension in config') {
    router = new SemanticRouter({ dimension: DEFAULT_DIMENSION }); // fail loud in dev, default in prod
  } else throw e;
}

Prevention

When it happens

Trigger: new SemanticRouter({} as any) or new SemanticRouter({metric:'cosine'}) with dimension forgotten; dimension passed as a string ('384') from env/config parsing; config objects built conditionally where the dimension field is only set on one branch; new SemanticRouter(null).

Common situations: Config loaded from JSON/env where everything arrives as strings; switching embedding models and deleting the dimension field while refactoring; partial config objects satisfying TypeScript via casts; copying router setup code that assumed a default dimension (there is none).

Understand the failure class

Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.

Related errors


AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18). Data as JSON: /api/errors/7ae72da97f4d9bd0. Report an issue: GitHub.

Appendix: source

Thrown at v3/@claude-flow/cli/src/ruvector/semantic-router.ts:41

  dimension: number;
  metric?: 'cosine' | 'euclidean' | 'dotProduct';
}

interface StoredIntent {
  name: string;
  embeddings: Float32Array[];
  metadata: Record<string, unknown>;
}

export class SemanticRouter {
  private dimension: number;
  private metric: 'cosine' | 'euclidean' | 'dotProduct';
  private intents: Map<string, StoredIntent> = new Map();
  private totalVectors = 0;

  constructor(config: RouterConfig) {
    if (!config || typeof config.dimension !== 'number') {
      throw new Error('SemanticRouter requires a dimension in config');
    }
    this.dimension = config.dimension;
    this.metric = config.metric ?? 'cosine';
  }

  /**
   * Add an intent with pre-computed embeddings
   */
  addIntentWithEmbeddings(
    name: string,
    embeddings: Float32Array[],
    metadata: Record<string, unknown> = {}
  ): void {
    if (!name || !Array.isArray(embeddings)) {
      throw new Error('Must provide name and embeddings array');
    }

    // Validate embeddings

View on GitHub (pinned to fa13ee4ad6)