{"record":{"id":"1b442ef2dc27a8b4","repo":"ellite/Wallos","slug":"invalid-digits-parameter","errorCode":null,"errorMessage":"Invalid \"digits\" parameter.","messagePattern":"Invalid \"digits\" parameter\\.","errorType":"exception","errorClass":"InvalidArgumentException","httpStatus":null,"severity":"error","filePath":"libs/OTPHP/ParameterTrait.php","lineNumber":88,"sourceCode":"    public function setIssuer(string $issuer): void\n    {\n        $this->setParameter('issuer', $issuer);\n    }\n\n    public function isIssuerIncludedAsParameter(): bool\n    {\n        return $this->issuer_included_as_parameter;\n    }\n\n    public function setIssuerIncludedAsParameter(bool $issuer_included_as_parameter): void\n    {\n        $this->issuer_included_as_parameter = $issuer_included_as_parameter;\n    }\n\n    public function getDigits(): int\n    {\n        $value = $this->getParameter('digits');\n        (is_int($value) && $value > 0) || throw new InvalidArgumentException('Invalid \"digits\" parameter.');\n\n        return $value;\n    }\n\n    public function getDigest(): string\n    {\n        $value = $this->getParameter('algorithm');\n        (is_string($value) && $value !== '') || throw new InvalidArgumentException('Invalid \"algorithm\" parameter.');\n\n        return $value;\n    }\n\n    public function hasParameter(string $parameter): bool\n    {\n        return array_key_exists($parameter, $this->parameters);\n    }\n\n    public function getParameter(string $parameter): mixed","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/ellite/Wallos/blob/52820e87ca5a6e105fdbb7f1c0c681bc0cfee2fd/libs/OTPHP/ParameterTrait.php#L70-L106","documentation":"This is a validation guard inside OTPHP's ParameterTrait: getDigits() fetches the 'digits' parameter from the OTP parameters array and throws InvalidArgumentException when it is absent, not an integer, or not strictly greater than 0. It fires when code reads the digit count of an OTP whose 'digits' parameter was never set (or was set to an invalid value, e.g. via setParameter) — typically when an object was built from a malformed provisioning URI missing the digits claim. Fix by setting a positive integer digit count (e.g. 6 or 8) before calling getDigits().","triggerScenarios":"Setting digits to 0, a negative number, or a numeric string (e.g. from JSON/URI parsing '6'), then calling at()/now()/verify() which reads getDigits(). Note the parameter map may normalize some values, but raw invalid ints reach this check.","commonSituations":"Loading a provisioning URI with digits=0 or non-numeric digits; config values stored as strings in DB; custom digits like 3 or 20 rejected upstream but 0/-1 slipping here.","solutions":["Pass a valid positive int (commonly 6 or 8) to TOTP::create($secret, null, 'sha1', 6).","Cast config/DB values: (int) $digits and check $digits > 0 before use.","Fix the provisioning URI's digits= query parameter to a positive integer.","Guard: if (!is_int($digits) || $digits <= 0) { normalize before constructing the OTP object. }"],"exampleFix":"// before\n$totp->setParameter('digits', '6'); // string from config\n// after\n$digits = (int) $config['digits'];\n$totp->setParameter('digits', $digits > 0 ? $digits : 6);","handlingStrategy":"validation","validationCode":"$digits = (int) ($config['digits'] ?? 6);\nif ($digits <= 0) {\n    $digits = 6;\n}\n$totp->setParameter('digits', $digits);","typeGuard":"function normalizeDigits(mixed $value): int {\n    return is_int($value) && $value > 0 ? $value : 6;\n}","tryCatchPattern":"try {\n    $code = $otp->now();\n} catch (InvalidArgumentException $e) {\n    log_error('Invalid OTP parameters', ['exception' => $e->getMessage()]);\n    throw new OtpConfigurationException($e);\n}","preventionTips":["Cast digits from config/DB/URIs to int before use","Allow-list acceptable digit counts (6, 8) at the config layer","Fix digits= values in provisioning URIs to positive integers","Round-trip test: build OTP -> export URI -> re-import and compare codes"],"tags":["php","otp","digits","validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"52820e87ca5a6e105fdbb7f1c0c681bc0cfee2fd","analyzedAt":"2026-09-13T14:09:30.873Z","contentChangedAt":"2026-09-13T14:09:30.873Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}