BabylonJS/Babylon.js · error

Cannot perform bitwise XOR on ${a} and ${b}

Error message

Cannot perform bitwise XOR on ${a} and ${b}

What it means

The BitwiseXor flow graph block supports exactly three shapes: two booleans (a !== b), two plain numbers (a ^ b), or two FlowGraphInteger objects (a.value ^ b.value). Mixed kinds or any other type (string, vector, object other than FlowGraphInteger) reaches the throw. The two operands must share the same representation.

Source

Thrown at packages/dev/core/src/FlowGraph/Blocks/Data/Math/flowGraphMathBlocks.pure.ts:1281

/**
 * Bitwise XOR operation
 */
export class FlowGraphBitwiseXorBlock extends FlowGraphBinaryOperationBlock<FlowGraphBitwiseTypes, FlowGraphBitwiseTypes, FlowGraphBitwiseTypes> {
    constructor(config?: IFlowGraphBlockConfiguration) {
        super(
            getRichTypeByFlowGraphType(config?.valueType || FlowGraphTypes.Integer),
            getRichTypeByFlowGraphType(config?.valueType || FlowGraphTypes.Integer),
            getRichTypeByFlowGraphType(config?.valueType || FlowGraphTypes.Integer),
            (a, b) => {
                if (typeof a === "boolean" && typeof b === "boolean") {
                    return a !== b;
                } else if (typeof a === "number" && typeof b === "number") {
                    return a ^ b;
                } else if (typeof a === "object" && typeof b === "object") {
                    return new FlowGraphInteger(a.value ^ b.value);
                } else {
                    throw new Error(`Cannot perform bitwise XOR on ${a} and ${b}`);
                }
            },
            FlowGraphBlockNames.BitwiseXor,
            config
        );
    }
}

/**
 * Bitwise left shift operation
 */
export class FlowGraphBitwiseLeftShiftBlock extends FlowGraphBinaryOperationBlock<FlowGraphInteger, FlowGraphInteger, FlowGraphInteger> {
    constructor(config?: IFlowGraphBlockConfiguration) {
        super(
            RichTypeFlowGraphInteger,
            RichTypeFlowGraphInteger,
            RichTypeFlowGraphInteger,
            (a, b) => new FlowGraphInteger(a.value << b.value),

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Match operand types: use two booleans for logical XOR, or two numbers / two FlowGraphInteger for bitwise XOR.
  2. Convert one operand: use intBlock.value.value (number) or wrap the number in new FlowGraphInteger(n).
  3. Audit the graph connections feeding the block and fix the wrong-typed wire.

Example fix

// before: FlowGraphInteger XOR boolean -> throws
xorBlock.a.connect(intBlock.value); // FlowGraphInteger
xorBlock.b.connect(toggleBlock.output); // boolean

// after: both FlowGraphInteger
xorBlock.a.connect(intBlock.value);
xorBlock.b.connect(new FlowGraphInteger(toggleBlock.output ? 1 : 0));
Defensive patterns

Strategy: type-guard

Validate before calling

// before BitwiseXor block runs
function bitwiseCompatible(a, b) {
  const bool = (v) => typeof v === 'boolean';
  const num = (v) => typeof v === 'number';
  const int = (v) => typeof v === 'object' && v !== null && 'value' in v;
  return (bool(a) && bool(b)) || (num(a) && num(b)) || (int(a) && int(b));
}
if (!bitwiseCompatible(xorInputA, xorInputB)) throw new TypeError('Bitwise XOR needs two booleans, two numbers, or two FlowGraphIntegers');

Type guard

function isFlowGraphInteger(v): v is FlowGraphInteger {
  return typeof v === 'object' && v !== null && 'value' in v && typeof (v as any).value === 'number';
}
function sameOperandKind(a: unknown, b: unknown): boolean {
  return isFlowGraphInteger(a) === isFlowGraphInteger(b) && typeof a === typeof b;
}

Try / catch

try {
  result = xorBlock.evaluate(context);
} catch (e) {
  if (e.message.startsWith('Cannot perform bitwise XOR')) {
    result = toNum(a) ^ toNum(b); // normalize then retry
  } else { throw e; }
}

Prevention

When it happens

Trigger: Executing FlowGraphBitwiseXorBlock with mismatched inputs: boolean XOR number, number XOR FlowGraphInteger, FlowGraphInteger XOR boolean, or a non-supported value type on either port.

Common situations: Toggling a boolean flag with a numeric mask in one block; an upstream block changed from returning number to FlowGraphInteger (or vice versa) after an engine upgrade; copy-pasted graph wiring with inconsistent types.

Related errors


AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30). Data as JSON: /api/errors/bea2e22604ce8172. Report an issue: GitHub.