thephpleague/flysystem · error · UnableToProvideChecksum
Unable to get checksum for $path: $reason
Error message
Unable to get checksum for $path: $reason
What it means
AsyncAwsS3Adapter::checksum() obtains the ETag by calling fetchFileMetadata() (a HeadObject request). When that metadata retrieval fails for any reason, the UnableToRetrieveMetadata exception is rethrown as UnableToProvideChecksum with the message 'Unable to get checksum for $path: $reason'. The original exception is chained as $previous, so the reason string comes from the underlying failure.
Source
Thrown at src/AsyncAwsS3/AsyncAwsS3Adapter.php:565
try {
return $this->client->getUrl($this->bucket, $this->prefixer->prefixPath($path));
} catch (Throwable $exception) {
throw UnableToGeneratePublicUrl::dueToError($path, $exception);
}
}
public function checksum(string $path, Config $config): string
{
$algo = $config->get('checksum_algo', 'etag');
if ($algo !== 'etag') {
throw new ChecksumAlgoIsNotSupported();
}
try {
$metadata = $this->fetchFileMetadata($path, 'checksum')->extraMetadata();
} catch (UnableToRetrieveMetadata $exception) {
throw new UnableToProvideChecksum($exception->reason(), $path, $exception);
}
if ( ! isset($metadata['ETag'])) {
throw new UnableToProvideChecksum('ETag header not available.', $path);
}
return trim($metadata['ETag'], '"');
}
public function temporaryUrl(string $path, DateTimeInterface $expiresAt, Config $config): string
{
try {
$request = new GetObjectRequest([
'Bucket' => $this->bucket,
'Key' => $this->prefixer->prefixPath($path),
] + $config->get('get_object_options', []));
return $this->client->presign($request, DateTimeImmutable::createFromInterface($expiresAt));View on GitHub (pinned to b277b5dc3d)
Solutions
- Verify the path exists first with $filesystem->fileExists($path) and handle the race window gracefully.
- Inspect $exception->getPrevious() to find the real cause (404, 403, DNS, credentials) and fix that.
- For permission errors, grant s3:GetObject (and s3:ListBucket on the bucket) to the credentials used by the AsyncAws S3Client.
- Catch UnableToProvideChecksum at the call site and retry or degrade, since transient network errors surface here too.
Example fix
// before
$checksum = $filesystem->checksum('reports/2024/q1.csv'); // file was deleted -> throws
// after
if ( ! $filesystem->fileExists('reports/2024/q1.csv')) {
throw new RuntimeException('Report missing, cannot verify integrity.');
}
try {
$checksum = $filesystem->checksum('reports/2024/q1.csv', ['checksum_algo' => 'etag']);
} catch (UnableToProvideChecksum $e) {
$reason = $e->getPrevious() ? $e->getPrevious()->getMessage() : $e->getMessage();
// handle 403 (permissions), 404 (raced delete), network errors
} Defensive patterns
Strategy: try-catch
Validate before calling
if ( ! $filesystem->fileExists($path)) {
throw new InvalidArgumentException("Cannot checksum missing path: {$path}");
}
// fileExists uses HeadObject, so permission problems surface there with clearer context Try / catch
use League\Flysystem\UnableToProvideChecksum;
try {
$etag = $filesystem->checksum($path);
} catch (UnableToProvideChecksum $e) {
$previous = $e->getPrevious();
// branch on the wrapped UnableToRetrieveMetadata reason (404 vs 403 vs network)
log_warning('checksum failed', ['path' => $path, 'reason' => $e->getMessage()]);
throw $e;
} Prevention
- Grant the client IAM permission for HeadObject (s3:GetObject + s3:ListBucket) so 404s are distinguishable from 403s.
- Run fileExists() before checksumming when the file's presence is not guaranteed.
- In retry policies, retry only when the chained exception indicates a transport error, not 404/403.
When it happens
Trigger: $adapter->checksum() or $filesystem->checksum() on a path that does not exist (404), the IAM principal lacks s3:GetObject / s3:ListBucket permission so HeadObject is denied, the S3-compatible endpoint is unreachable, credentials are expired, or the path resolves to a directory.
Common situations: Checksumming a file that was concurrently deleted; wrong key case or missing path prefix; read-only IAM roles that allow ListObjects but not HeadObject; S3-compatible services (MinIO, R2, third-party gateways) with auth or clock-skew problems.
Related errors
- ETag header not available.
- Unable to get checksum for $path: $reason
- Unable to get checksum for $path: $reason
- Unable to get checksum for $path: $reason
- Unable to get checksum for $path: $reason
AI-assisted analysis of thephpleague/flysystem@b277b5dc3d (2026-08-17).
Data as JSON: /api/errors/c74f56ac341be6e6.
Report an issue: GitHub.