Skip to content

Corrupted variable type Argument #1 ($string) must be of type string, string given #21972

Closed

Description

@susnux

Description

The following code:

<?php
declare(strict_types=1);
// ...
class MyClass {
    // ...
    public function getValueBool(): bool {
        $b = strtolower($this->getTypedValue(), ValueType::BOOL));
        // ...
    }
    protected function getTypedValue(): string {
        // ...
    }
}

Resulted in this output:

TypeError: strtolower(): Argument #1 ($string) must be of type string, string given

But I expected this output instead:

$b = "false"

PHP Version

8.4.20

Operating System

Ubuntu / docker


What is confusing here is that we use strict types thus the return type of getTypedValue always has to be a string. This does not throw a TypeError so it should be a string.
If we add more debugging to the return value before putting it to strtolower:

$a = $this->getTypedValue();
// do debugging here
$b = strtolower($a);
  • printing the value: "false"
  • gettype($a) type: "unknown type"
  • check if its a class (print $a::class): Cannot use \"::class\" on string

In our real code base its this line:
https://github.com/nextcloud/server/blob/57a2630be741ce039929830294b93982587e9ec3/lib/private/Config/UserConfig.php#L708

We received a bug ourself but I suspect this is a php bug from the TypeError received and the "unknown type" type

Activity

  1. bwoebi commented on May 7, 2026

    @bwoebi
    Member

    From my experience, without looking into details, "string given", when string is expected, happens when references containing a string are passed around, without references being expected (i.e. there was no automatic unwrapping of the reference happening due to some reason).

  2. LamentXU123 commented on May 7, 2026

    @LamentXU123
    Member

    I think this happens since a typed by-value return could leak an internal reference wrapper after a by-reference argument call. OPcache could then infer the returned value as string and elide later checks, while the actual zval still had IS_REFERENCE at the outer level. (so when you use gettype its unknown type)

    This is a simple fix I guess :) See if this works #21973

  3. susnux commented on Jun 30, 2026

    @susnux
    Author

    Resolved with #21973 🥳

  4. salmart-dev commented on Jun 30, 2026

    @salmart-dev

    It seems like the underlying bug affects PHP 8.3.31 too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions