paragonie/random_compat · error · TypeError
RandomCompat_substr(): Third argument should be an integer…
Error message
RandomCompat_substr(): Third argument should be an integer, or omitted
What it means
RandomCompat_substr()'s third parameter $length must be an integer or omitted (null, meaning 'rest of string'). When a non-int, non-null value (float, numeric string, bool) is supplied, the function throws TypeError. Note the library computes $length itself when null, because mb_substr($str, 0, NULL, '8bit') returns '' on PHP 5.3 — so passing null is always safe and correct.
Solutions
- Cast deliberately: $length = (int) $len after verifying it is numeric.
- Use round()/floor() then cast when deriving lengths from division: $length = (int) ceil($size / 2).
- Omit the parameter entirely (pass null) to mean 'to end of string' — the library computes it safely.
- Validate with is_int($length) at the caller boundary before invoking.
Example fix
// before $length = ceil(strlen($str) / 2); // float $half = RandomCompat_substr($str, 0, $length); // after $length = (int) ceil(RandomCompat_strlen($str) / 2); $half = RandomCompat_substr($str, 0, $length);
Defensive patterns
Strategy: validation
Validate before calling
if ($length !== null && !is_int($length)) {
$length = (int) $length; // verify numeric-ness first for untrusted input
}
$part = RandomCompat_substr($str, $start, $length); Type guard
function isValidLength($value): bool {
return $value === null || is_int($value);
}
$part = isValidLength($length)
? RandomCompat_substr($str, $start, $length)
: RandomCompat_substr($str, $start); Try / catch
try {
$part = RandomCompat_substr($str, $start, $length);
} catch (TypeError $e) {
// non-int length; fall back to rest-of-string
$part = RandomCompat_substr($str, $start);
} Prevention
- Pass null (or omit) for 'to end of string' — the library computes it safely even on PHP 5.3.
- Cast results of division/ceil/floor to int before using as length.
- Validate lengths from JSON/YAML/env which often arrive as strings.
- Keep chunk-size math in one helper that guarantees int output.
When it happens
Trigger: Calling RandomCompat_substr($str, $start, $length) where $length is a float from arithmetic (e.g. ceil(strlen($s)/2)), a numeric string from config/JSON ("16"), or a bool from a failed comparison. Only the elseif branch fires — $start was already a valid int.
Common situations: Computing half-lengths or chunk sizes with division producing floats; JSON/env config delivering lengths as strings; passing true/false from a conditional expression by accident; older PHP returning floats from certain math functions.
Understand the failure class
Background: "must be a positive integer", "cannot be empty", "invalid argument": how invalid-argument errors work across open-source libraries — this error's family across 33 libraries.
Related errors
- RandomCompat_substr(): Second argument should be an integer
- RandomCompat_substr(): First argument should be a string
- RandomCompat_strlen() expects a string
- Expected an integer.
- random_bytes(): $bytes must be an integer
AI-assisted analysis of paragonie/random_compat@b5d188cc9d (2026-09-13).
Data as JSON: /api/errors/060346f8c88e6f04.
Report an issue: GitHub.
Appendix: source
Thrown at lib/byte_safe_strings.php:125
'RandomCompat_substr(): First argument should be a string'
);
}
if (!is_int($start)) {
throw new TypeError(
'RandomCompat_substr(): Second argument should be an integer'
);
}
if ($length === null) {
/**
* mb_substr($str, 0, NULL, '8bit') returns an empty string on
* PHP 5.3, so we have to find the length ourselves.
*/
/** @var int $length */
$length = RandomCompat_strlen($binary_string) - $start;
} elseif (!is_int($length)) {
throw new TypeError(
'RandomCompat_substr(): Third argument should be an integer, or omitted'
);
}
// Consistency with PHP's behavior
if ($start === RandomCompat_strlen($binary_string) && $length === 0) {
return '';
}
if ($start > RandomCompat_strlen($binary_string)) {
return '';
}
return (string) mb_substr(
(string) $binary_string,
(int) $start,
(int) $length,
'8bit'
);View on GitHub (pinned to b5d188cc9d)