{"record":{"id":"21cead502ae31189","repo":"ellite/Wallos","slug":"the-s-digest-is-not-supported","errorCode":null,"errorMessage":"The \"%s\" digest is not supported.","messagePattern":"The \"(.+?)\" digest is not supported\\.","errorType":"exception","errorClass":"InvalidArgumentException","httpStatus":null,"severity":"error","filePath":"libs/OTPHP/ParameterTrait.php","lineNumber":163,"sourceCode":"\n    /**\n     * @return array<non-empty-string, callable>\n     */\n    protected function getParameterMap(): array\n    {\n        return [\n            'label' => function (string $value): string {\n                assert($value !== '');\n                $this->hasColon($value) === false || throw new InvalidArgumentException(\n                    'Label must not contain a colon.'\n                );\n\n                return $value;\n            },\n            'secret' => static fn (string $value): string => strtoupper(trim($value, '=')),\n            'algorithm' => static function (string $value): string {\n                $value = strtolower($value);\n                in_array($value, hash_algos(), true) || throw new InvalidArgumentException(sprintf(\n                    'The \"%s\" digest is not supported.',\n                    $value\n                ));\n\n                return $value;\n            },\n            'digits' => static function ($value): int {\n                $value > 0 || throw new InvalidArgumentException('Digits must be at least 1.');\n\n                return (int) $value;\n            },\n            'issuer' => function (string $value): string {\n                assert($value !== '');\n                $this->hasColon($value) === false || throw new InvalidArgumentException(\n                    'Issuer must not contain a colon.'\n                );\n\n                return $value;","sourceCodeStart":145,"sourceCodeEnd":181,"githubUrl":"https://github.com/ellite/Wallos/blob/52820e87ca5a6e105fdbb7f1c0c681bc0cfee2fd/libs/OTPHP/ParameterTrait.php#L145-L181","documentation":"The 'algorithm' entry of the parameter map lowercases the value and checks it against hash_algos(). If the requested HMAC digest is not provided by the installed PHP hash extension, setParameter('algorithm', ...) throws this InvalidArgumentException.","triggerScenarios":"Calling setParameter('algorithm', 'sha3-256') or any algorithm name not present in hash_algos(); also misspelled names like 'sha257' or legacy names like 'hmac-sha1'.","commonSituations":"Using an algorithm an authenticator app supports but the PHP build does not (or vice versa); running on a PHP compiled without certain hash algorithms; typos in algorithm names in config files.","solutions":["Use a standard digest: 'sha1', 'sha256', or 'sha512'","Verify with in_array($algo, hash_algos(), true) before setting","If the algorithm must exist, install/enable the PHP hash extension providing it"],"exampleFix":"// before\n$otp->setParameter('algorithm', 'HMAC-SHA256');\n// after\n$otp->setParameter('algorithm', 'sha256');","handlingStrategy":"validation","validationCode":"$algo = strtolower($config['algorithm'] ?? 'sha1');\nif (!in_array($algo, hash_algos(), true)) {\n    $algo = 'sha1';\n}\n$otp->setParameter('algorithm', $algo);","typeGuard":null,"tryCatchPattern":"try {\n    $otp->setParameter('algorithm', $config['algorithm']);\n} catch (\\InvalidArgumentException $e) {\n    $otp->setParameter('algorithm', 'sha1');\n}","preventionTips":["Restrict config to sha1/sha256/sha512","Test algorithm names against hash_algos() at app startup","Remember the library lowercases names; 'SHA1' becomes 'sha1' automatically"],"tags":["php","otp","hash-algorithm"],"backgroundTag":"unsupported-enum-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"}