heygen-com/hyperframes · error

Unknown effect type: ${type}

Error message

Unknown effect type: ${type}

What it means

buildFxNode() looks up the effect `type` in the registry (getAudioFxDef/BY_ID, keyed by HF_AUDIO_FX ids) and throws if no definition exists. This guards the runtime Web Audio graph builder — only effect ids declared in HF_AUDIO_FX can be instantiated. Unlike parseAudioFxChain (which rejects unknown ids at load time), this fires at graph construction, e.g. when code assembles a node programmatically with a typo'd or outdated id.

Source

Thrown at packages/core/src/audio/audioFxGraph.ts:353

  waveshaper,
  "delay-feedback": delayFeedback,
  "chorus-lfo": chorusLfo,
  "allpass-phaser": allpassPhaser,
  convolver,
};

/** Effect ids whose Web Audio node needs a worklet module registered first. */
export function chainNeedsWorklets(chain: HfAudioFxChain): boolean {
  return chain.nodes.some((node) => getAudioFxDef(node.type)?.web.startsWith("worklet-") ?? false);
}

export function buildFxNode(
  ctx: BaseAudioContext,
  type: string,
  params: HfAudioFxParamValues,
): FxNodeHandle {
  const def = getAudioFxDef(type);
  if (!def) throw new Error(`Unknown effect type: ${type}`);
  const resolved = normalizeAudioFxParams(type, params);
  // One-pole is a different node type, not a different parameter value.
  if ((type === "highpass" || type === "lowpass") && String(resolved.poles) === "1") {
    return onePoleBuilder(type)(ctx, resolved);
  }
  const builder = BUILDERS[def.web];
  if (!builder) throw new Error(`No Web Audio builder for ${def.web}`);
  return builder(ctx, resolved);
}

export interface FxChainHandle {
  input: AudioNode;
  output: AudioNode;
  /** Re-parameterise in place when the shape is unchanged; false if a rebuild is needed. */
  update(chain: HfAudioFxChain): boolean;
  dispose(): void;
}

View on GitHub (pinned to c2996c8626)

Solutions

  1. Use only ids exported in HF_AUDIO_FX_IDS; import and check membership before building.
  2. If you have a chain object, run it through parseAudioFxChain (or at least check each node.type against HF_AUDIO_FX_IDS) before calling buildFxNode so the error surfaces early with a clear message.
  3. Update to the current effect id after a rename — check the HF_AUDIO_FX array in packages/core/src/audioFx.ts for the canonical list.

Example fix

// before
const node = buildFxNode(ctx, "compressor", {}); // throws Unknown effect type

// after — guard against the registry first
import { HF_AUDIO_FX_IDS } from "@hyperframes/core";
const type = HF_AUDIO_FX_IDS.includes("worklet-compressor") ? "worklet-compressor" : undefined;
if (!type) throw new Error(`effect not available`);
const node = buildFxNode(ctx, type, {});
Defensive patterns

Strategy: type-guard

Validate before calling

import { HF_AUDIO_FX_IDS } from "@hyperframes/core";
const known = new Set(HF_AUDIO_FX_IDS);
if (!known.has(type)) throw new Error(`unsupported effect id: ${type}`);
const node = buildFxNode(ctx, type, params);

Type guard

import { HF_AUDIO_FX_IDS } from "@hyperframes/core";
const FX_ID_SET = new Set(HF_AUDIO_FX_IDS);
function isAudioFxId(type: string): type is string {
  return FX_ID_SET.has(type);
}

Try / catch

try { buildFxNode(ctx, type, params); }
catch (err) { if (/Unknown effect type/.test(String(err))) { /* pick a supported id */ } else throw err; }

Prevention

When it happens

Trigger: Calling buildFxNode(ctx, 'compressor', {...}) when the real id is 'worklet-compressor'; passing a user-typed or LLM-generated effect name not in HF_AUDIO_FX_IDS; a stale plugin/block referencing an id that was renamed or removed in a HyperFrames version bump.

Common situations: Custom composition authoring by hand with a guessed effect id; upgrading HyperFrames after an effect was renamed; loading a chain that bypassed parseAudioFxChain validation (e.g. constructed in memory).

Related errors


AI-assisted analysis of heygen-com/hyperframes@c2996c8626 (2026-08-12). Data as JSON: /api/errors/8bdb29438a2a4d67. Report an issue: GitHub.