{"record":{"id":"160e7dfd72bb1411","repo":"thephpleague/flysystem","slug":"invalid-visibility-provided-expected-expectedme","errorCode":null,"errorMessage":"Invalid visibility provided. Expected {$expectedMessage}, received {$provided}","messagePattern":"Invalid visibility provided\\. Expected (.+?), received (.+?)","errorType":"exception","errorClass":"InvalidVisibilityProvided","httpStatus":null,"severity":"error","filePath":"src/InvalidVisibilityProvided.php","lineNumber":18,"sourceCode":"<?php\n\ndeclare(strict_types=1);\n\nnamespace League\\Flysystem;\n\nuse InvalidArgumentException;\n\nuse function var_export;\n\nclass InvalidVisibilityProvided extends InvalidArgumentException implements FilesystemException\n{\n    public static function withVisibility(string $visibility, string $expectedMessage): InvalidVisibilityProvided\n    {\n        $provided = var_export($visibility, true);\n        $message = \"Invalid visibility provided. Expected {$expectedMessage}, received {$provided}\";\n\n        throw new InvalidVisibilityProvided($message);\n    }\n}\n","sourceCodeStart":1,"sourceCodeEnd":21,"githubUrl":"https://github.com/thephpleague/flysystem/blob/b277b5dc3d56650b68904117124e79c851e12376/src/InvalidVisibilityProvided.php#L1-L21","documentation":"PortableVisibilityGuard::guardAgainstInvalidInput() (used when normalizing visibility settings) only accepts the exact strings Visibility::PUBLIC ('public') and Visibility::PRIVATE ('private'). Anything else — different casing, whitespace, integers, or arbitrary ACL words like 'readonly' — triggers InvalidVisibilityProvided::withVisibility(), producing 'Invalid visibility provided. Expected either Visibility::PUBLIC or Visibility::PRIVATE, received <var_export of value>'. It extends InvalidArgumentException, marking it a programming/config error rather than an I/O failure.","triggerScenarios":"Calling $filesystem->write($path, $contents, ['visibility' => 'Public']) or ->setVisibility($path, 'read-only'); passing an int (e.g. 1/0 or octal 0644 leftovers) so var_export prints 1; reading visibility from user input or env vars without whitelisting; default visibility configured with a misspelled constant.","commonSituations":"Migrating Flysystem v1/v2 code that used the old integer-ish or differently-cased visibility values; env/config values like 'PUBLIC', 'public ', or 'private-' slipping through; frontend-supplied visibility strings forwarded verbatim.","solutions":["Use the constants: League\\Flysystem\\Visibility::PUBLIC and League\\Flysystem\\Visibility::PRIVATE.","Whitelist and map external input before it reaches Flysystem: in_array($v, ['public', 'private'], true) with normalization (trim + strtolower).","Set default visibility in Filesystem/adapter constructors from the same constants, not free-form strings.","Drop legacy octal/numeric visibility remnants from old configs — Flysystem 3+ uses string constants only."],"exampleFix":"// before\n$filesystem->write('file.txt', $data, ['visibility' => $_ENV['DEFAULT_VISIBILITY']]); // 'PUBLIC' -> throws\n\n// after\nuse League\\Flysystem\\Visibility;\n\n$raw = strtolower(trim($_ENV['DEFAULT_VISIBILITY'] ?? 'private'));\n$visibility = $raw === 'public' ? Visibility::PUBLIC : Visibility::PRIVATE;\n$filesystem->write('file.txt', $data, ['visibility' => $visibility]);","handlingStrategy":"type-guard","validationCode":"use League\\Flysystem\\Visibility;\n\n// Whitelist external input before it reaches Flysystem\n$visibility = strtolower(trim($configValue));\nif ( ! in_array($visibility, [Visibility::PUBLIC, Visibility::PRIVATE], true)) {\n    throw new InvalidArgumentException(\"Visibility must be 'public' or 'private', got '{$configValue}'.\");\n}","typeGuard":"/**\n * Narrow arbitrary config/user input to a valid Flysystem visibility constant.\n */\nfunction toFlysystemVisibility(mixed $value): ?string\n{\n    if ( ! is_string($value)) {\n        return null;\n    }\n    $normalized = strtolower(trim($value));\n\n    return in_array($normalized, ['public', 'private'], true) ? $normalized : null;\n}","tryCatchPattern":"use League\\Flysystem\\InvalidVisibilityProvided;\n\ntry {\n    $filesystem->write($path, $contents, ['visibility' => $visibility]);\n} catch (InvalidVisibilityProvided $e) {\n    // config/programming error: surface immediately with the config source\n    throw new ConfigurationError(\"Bad visibility in deploy config: {$e->getMessage()}\", 0, $e);\n}","preventionTips":["Always pass Visibility::PUBLIC / Visibility::PRIVATE constants — never raw strings or ints from env/user input.","Normalize (trim + lowercase) and whitelist visibility values at the config boundary.","Purge legacy octal/numeric visibility settings left over from Flysystem v1/v2 during upgrades.","Cover visibility config with a unit test asserting the constants."],"tags":["php","flysystem","visibility","invalid-argument","configuration","acl"],"backgroundTag":"invalid-visibility-value","analyzedSha":"b277b5dc3d56650b68904117124e79c851e12376","analyzedAt":"2026-08-17T04:28:35.741Z","schemaVersion":2},"datasetVersion":"2026-08-17T09:17:11.063Z"}