ellite/Wallos · error · InvalidArgumentException

Digits must be at least 1.

Error message

Digits must be at least 1.

What it means

The 'digits' entry of the parameter map coerces the assigned value and requires it to be strictly greater than 0. Assigning 0, a negative number, or a non-numeric value via setParameter('digits', ...) throws this InvalidArgumentException because an OTP code must have at least one digit.

Solutions

  1. Pass a positive integer, typically 6 or 8, to setParameter('digits', ...)
  2. Validate/clamp the configured value with max(1, (int)$value) before assigning
  3. Fix the upstream config or DB default that produced 0

Example fix

// before
$otp->setParameter('digits', $config['otp_length'] ?? 0);
// after
$otp->setParameter('digits', max(1, (int)($config['otp_length'] ?? 6)));
Defensive patterns

Strategy: validation

Validate before calling

$digits = (int)($config['digits'] ?? 6);
if ($digits < 1) {
    $digits = 6;
}
$otp->setParameter('digits', $digits);

Try / catch

try {
    $otp->setParameter('digits', $value);
} catch (\InvalidArgumentException $e) {
    $otp->setParameter('digits', 6);
}

Prevention

When it happens

Trigger: Calling setParameter('digits', 0) or setParameter('digits', -6); passing a string like 'abc' that compares non-numerically; passing null (null > 0 is false in loose comparison).

Common situations: Reading the digit count from user config or a database column that defaults to 0; parsing a provisioning URI with digits=0; a template variable left empty.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of ellite/Wallos@52820e87ca (2026-09-13). Data as JSON: /api/errors/1a23aa6bfb5cb58b. Report an issue: GitHub.

Appendix: source

Thrown at libs/OTPHP/ParameterTrait.php:171

                assert($value !== '');
                $this->hasColon($value) === false || throw new InvalidArgumentException(
                    'Label must not contain a colon.'
                );

                return $value;
            },
            'secret' => static fn (string $value): string => strtoupper(trim($value, '=')),
            'algorithm' => static function (string $value): string {
                $value = strtolower($value);
                in_array($value, hash_algos(), true) || throw new InvalidArgumentException(sprintf(
                    'The "%s" digest is not supported.',
                    $value
                ));

                return $value;
            },
            'digits' => static function ($value): int {
                $value > 0 || throw new InvalidArgumentException('Digits must be at least 1.');

                return (int) $value;
            },
            'issuer' => function (string $value): string {
                assert($value !== '');
                $this->hasColon($value) === false || throw new InvalidArgumentException(
                    'Issuer must not contain a colon.'
                );

                return $value;
            },
        ];
    }

    /**
     * @param non-empty-string $value
     */
    private function hasColon(string $value): bool

View on GitHub (pinned to 52820e87ca)