symfony/var-dumper · error · RuntimeException

Unexpected Stub type

Error message

Unexpected Stub type: "%s".

What it means

During Data::dumpItem() traversal, each item's Stub must have a known type (TYPE_REF, TYPE_STRING, TYPE_ARRAY, TYPE_OBJECT, TYPE_RESOURCE, TYPE_SCALAR). An unrecognized Stub->type value indicates a corrupted or hand-built Stub, or an internal var-dumper version incompatibility, and triggers the RuntimeException default-case failure.

Solutions

  1. Use only Stub::TYPE_* constants when constructing Stubs; verify custom code against symfony/var-dumper's Stub class
  2. Ensure all symfony/var-dumper sub-components (cloner, dumper) are the same installed version (composer update together)
  3. Inspect the item->type value logged in the exception to find who produced the invalid Stub

Example fix

// before
$stub->type = 42;
// after
$stub->type = Stub::TYPE_OBJECT;
Defensive patterns

Strategy: try-catch

Validate before calling

$known = [\Symfony\Component\VarDumper\Cloner\Stub::TYPE_REF, \Symfony\Component\VarDumper\Cloner\Stub::TYPE_STRING, \Symfony\Component\VarDumper\Cloner\Stub::TYPE_ARRAY, \Symfony\Component\VarDumper\Cloner\Stub::TYPE_OBJECT, \Symfony\Component\VarDumper\Cloner\Stub::TYPE_RESOURCE, \Symfony\Component\VarDumper\Cloner\Stub::TYPE_SCALAR];
if (isset($stub->type) && !in_array($stub->type, $known, true)) {
    throw new \LogicException('Invalid stub type before dump: '.var_export($stub->type, true));
}

Type guard

function hasValidStubType(?\Symfony\Component\VarDumper\Cloner\Stub $stub): bool {
    return $stub !== null && in_array($stub->type, [\Symfony\Component\VarDumper\Cloner\Stub::TYPE_REF, \Symfony\Component\VarDumper\Cloner\Stub::TYPE_STRING, \Symfony\Component\VarDumper\Cloner\Stub::TYPE_ARRAY, \Symfony\Component\VarDumper\Cloner\Stub::TYPE_OBJECT, \Symfony\Component\VarDumper\Cloner\Stub::TYPE_RESOURCE, \Symfony\Component\VarDumper\Cloner\Stub::TYPE_SCALAR], true);
}

Try / catch

try {
    $dumper->dump($data);
} catch (\RuntimeException $e) {
    if (str_starts_with($e->getMessage(), 'Unexpected Stub type:')) {
        // log item->type; check component version sync
    } else {
        throw $e;
    }
}

Prevention

When it happens

Trigger: Passing a Stub-like object with an out-of-range/unknown ->type constant into the dump pipeline (e.g. custom dumper/cloner code building Stubs manually), or mixing Stub constants from mismatched var-dumper component versions.

Common situations: Custom VarDumper extensions or cloned-data manipulation that fabricates Stubs; version drift between symfony/var-dumper cloner and dumper components where Stub::TYPE_* constants changed.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.


AI-assisted analysis of symfony/var-dumper@e9d9cf5dcd (2026-09-14). Data as JSON: /api/errors/d69a916a98be1988. Report an issue: GitHub.

Appendix: source

Thrown at Cloner/Data.php:373

                        if ($cursor->skipChildren) {
                            $withChildren = false;
                            $cut = -1;
                        } else {
                            $cut = $this->dumpChildren($dumper, $cursor, $refs, $children, $cut, $item->type, null !== $item->class);
                        }
                    } elseif ($children && 0 <= $cut) {
                        $cut += \count($children);
                    }
                    $cursor->skipChildren = false;
                    $dumper->leaveHash($cursor, $item->type, $item->class, $withChildren, $cut);
                    break;

                case Stub::TYPE_SCALAR:
                    $dumper->dumpScalar($cursor, 'default', $item->attr['value']);
                    break;

                default:
                    throw new \RuntimeException(\sprintf('Unexpected Stub type: "%s".', $item->type));
            }
        } elseif ('array' === $type) {
            $dumper->enterHash($cursor, Cursor::HASH_INDEXED, 0, false);
            $dumper->leaveHash($cursor, Cursor::HASH_INDEXED, 0, false, 0);
        } elseif ('string' === $type) {
            $dumper->dumpString($cursor, $item, false, 0);
        } else {
            $dumper->dumpScalar($cursor, $type, $item);
        }
    }

    /**
     * Dumps children of hash structures.
     *
     * @return int The final number of removed items
     */
    private function dumpChildren(DumperInterface $dumper, Cursor $parentCursor, array &$refs, array $children, int $hashCut, int $hashType, bool $dumpKeys): int
    {

View on GitHub (pinned to e9d9cf5dcd)