ellite/Wallos · error · InvalidArgumentException

Label must not contain a colon.

Error message

Label must not contain a colon.

What it means

The 'label' entry in the parameter map validates every value assigned via setParameter('label', ...). RFC 4226/6238 provisioning URIs use a colon to separate issuer from account name, so a label containing a colon would corrupt the URI and is rejected with this InvalidArgumentException.

Solutions

  1. Pass only the account name as the label and set the issuer separately via setParameter('issuer', ...)
  2. Strip the issuer prefix and colon from the string before assigning it
  3. URL-encode is not a workaround; the colon check applies to the raw value, so remove the colon

Example fix

// before
$otp->setLabel('Acme:alice@acme.com');
// after
$otp->setIssuer('Acme');
$otp->setLabel('alice@acme.com');
Defensive patterns

Strategy: validation

Validate before calling

$label = 'alice@acme.com';
if (str_contains($label, ':')) {
    throw new \LogicException('Label must not contain a colon');
}
$otp->setLabel($label);

Try / catch

try {
    $otp->setLabel($userInput);
} catch (\InvalidArgumentException $e) {
    $otp->setLabel(str_replace(':', '', $userInput));
}

Prevention

When it happens

Trigger: Calling setParameter('label', 'my:user@example.com') or any label string containing ':', which happens when users paste email-like identifiers that already embed an issuer prefix.

Common situations: Putting 'Issuer:user@email' into the label because the developer confused the label with the full provisioning-URI path; copying the whole 'Issuer:account' part from a generated otpauth URI instead of just the account part.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at libs/OTPHP/ParameterTrait.php:154

    public function setDigits(int $digits): void
    {
        $this->setParameter('digits', $digits);
    }

    public function setDigest(string $digest): void
    {
        $this->setParameter('algorithm', $digest);
    }

    /**
     * @return array<non-empty-string, callable>
     */
    protected function getParameterMap(): array
    {
        return [
            'label' => function (string $value): string {
                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.');

View on GitHub (pinned to 52820e87ca)