phalcon/cphalcon · error · Phalcon\Db\Exceptions\InvalidWkb

Invalid WKB: buffer too short for MySQL prefix

Error message

Invalid WKB: buffer too short for MySQL prefix

What it means

When the input is not a hex string, WkbParser assumes the MySQL internal geometry format — a 4-byte little-endian SRID prefix followed by standard WKB — so at least 5 bytes are required. Fewer than 5 bytes throw InvalidWkb('buffer too short for MySQL prefix') before parsing starts.

Source

Thrown at phalcon/Db/Geometry/WkbParser.zep:55

    public function parse(string raw) -> <GeometryInterface>
    {
        var srid = 0, body, arr;

        if raw === "" {
            throw new InvalidWkb("empty value");
        }

        /**
         * PostGIS returns EWKB as an even-length ASCII-hex string; MySQL
         * returns binary (4-byte LE SRID prefix + standard WKB). Real binary
         * WKB is not valid ASCII hex (it carries the 0x01 byte-order byte and
         * arbitrary double bytes), so this distinguishes the two.
         */
        if strlen(raw) % 2 === 0 && ctype_xdigit(raw) {
            let body = hex2bin(raw);
        } else {
            if strlen(raw) < 5 {
                throw new InvalidWkb("buffer too short for MySQL prefix");
            }

            let arr  = unpack("V", substr(raw, 0, 4)),
                srid = (int) arr[1],
                body = substr(raw, 4);
        }

        let this->buffer   = body,
            this->length   = strlen(body),
            this->position = 0;

        return this->readGeometry(srid);
    }

    protected function readGeometry(int outerSrid) -> <GeometryInterface>
    {
        var byteOrder, little, typeWord, geomCode, baseType, hasZ, hasM,
            srid, count, i, items;

View on GitHub (pinned to b7419de9cd)

Solutions

  1. Pass the geometry value exactly as the database driver returned it — no substr() or encoding conversion
  2. Fix storage: use a BLOB type large enough and re-insert valid geometries
  3. Catch InvalidWkb and quarantine the offending row instead of aborting the whole batch

Example fix

// before
$geom = $parser->parse($row['geom']); // truncated BLOB

// after
$raw  = $row['geom'];
$geom = (is_string($raw) && strlen($raw) >= 5) ? $parser->parse($raw) : null;
Defensive patterns

Strategy: try-catch

Validate before calling

if (!is_string($raw) || strlen($raw) < 5) {
    // cannot contain even the 4-byte SRID prefix + 1 byte of WKB
    return null;
}
return $parser->parse($raw);

Type guard

function isPlausibleBinaryWkb(mixed $value): bool
{
    return is_string($value) && strlen($value) >= 5;
}

Try / catch

try {
    $geom = $parser->parse($raw);
} catch (\Phalcon\Db\Exceptions\InvalidWkb $e) {
    $logger->warning('Rejected geometry payload', ['bytes' => strlen($raw)]);
    $geom = null;
}

Prevention

When it happens

Trigger: Passing a truncated geometry BLOB (under 5 bytes); feeding a short placeholder string that fails the hex check; BLOB values cut off by a too-small column type or by post-processing (substr, charset conversion).

Common situations: TINYBLOB/BLOB overflow truncating stored geometries; fixtures with placeholder values; binary values run through string functions or JSON round-trips that shorten them.

Related errors


AI-assisted analysis of phalcon/cphalcon@b7419de9cd (2026-08-21). Data as JSON: /api/errors/ab3e34381c61b654. Report an issue: GitHub.