ruvnet/ruflo · error

Unknown hyperbolic model: ${this.model}

Error message

Unknown hyperbolic model: ${this.model}

What it means

HyperbolicSpace.distance() dispatches on the model string to poincare/lorentz/klein/half_space formulas (hyperbolic.ts:305). The HyperbolicModel union has exactly those four members, so in typed TypeScript this is unreachable; at runtime any other string (typos, legacy names, unvalidated JSON config) falls through to the default branch and throws.

Source

Thrown at v3/@claude-flow/plugins/src/integrations/ruvector/hyperbolic.ts:305

   * - Klein: Converted to Poincare first
   * - Half-space: d(u,v) = arcosh(1 + ||u-v||^2 / (2*u_n*v_n))
   *
   * @param a - First point
   * @param b - Second point
   * @returns Geodesic distance
   */
  distance(a: number[], b: number[]): number {
    switch (this.model) {
      case 'poincare':
        return this.poincareDistance(a, b);
      case 'lorentz':
        return this.lorentzDistance(a, b);
      case 'klein':
        return this.kleinDistance(a, b);
      case 'half_space':
        return this.halfSpaceDistance(a, b);
      default:
        throw new Error(`Unknown hyperbolic model: ${this.model}`);
    }
  }

  /**
   * Computes distance in the Poincare ball model.
   *
   * Formula: d(u,v) = (2/sqrt|c|) * arctanh(sqrt|c| * ||(-u) +_M v||)
   *
   * Where +_M is Mobius addition.
   */
  private poincareDistance(u: number[], v: number[]): number {
    // Use Mobius addition: -u +_M v
    const negU = scale(u, -1);
    const diff = this.mobiusAdd(negU, v);
    const diffNorm = norm(diff);

    // d = (2/sqrt|c|) * arctanh(sqrt|c| * ||diff||)
    const scaledNorm = this._scale * diffNorm;

View on GitHub (pinned to fa13ee4ad6)

Solutions

  1. Use one of the four exact literals: 'poincare' | 'lorentz' | 'klein' | 'half_space'
  2. 'hyperboloid' maps to 'lorentz'; 'half-space'/'halfspace' map to 'half_space'
  3. Validate model strings at the boundary with a type guard before constructing the space

Example fix

// before
const space = new HyperbolicSpace('halfspace', -1); // typo
space.distance(a, b); // throws: Unknown hyperbolic model: halfspace

// after
const space = new HyperbolicSpace('half_space', -1);
space.distance(a, b);
Defensive patterns

Strategy: type-guard

Validate before calling

const MODELS = ['poincare', 'lorentz', 'klein', 'half_space'] as const;
if (!MODELS.includes(cfg.model)) {
  throw new TypeError(`model must be one of ${MODELS.join('|')}, got '${cfg.model}'`);
}
const space = new HyperbolicSpace(cfg.model, cfg.curvature);

Type guard

const HYPERBOLIC_MODELS = new Set(['poincare', 'lorentz', 'klein', 'half_space']);
function isHyperbolicModel(v: unknown): v is HyperbolicModel {
  return typeof v === 'string' && HYPERBOLIC_MODELS.has(v);
}

Try / catch

try {
  const d = space.distance(a, b);
} catch (err) {
  if (err instanceof Error && err.message.startsWith('Unknown hyperbolic model')) {
    throw new ConfigError(`Fix the model name: ${err.message}`); // config bug, do not retry
  }
  throw err;
}

Prevention

When it happens

Trigger: Constructing HyperbolicSpace with model 'halfspace' (missing underscore), 'Poincare' (capitalized), 'hyperboloid' (the concept's other name for lorentz), or a value read from env/JSON/database without validation, then calling distance(a, b).

Common situations: Config files authored from memory of the literature ('hyperboloid', 'half-space' with a hyphen); deserializing spaces persisted by older versions; JS consumers bypassing the TypeScript union.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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