Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

[Spanner] Retries of UNAVAILABLE errors when resuming a result stream not working properly

Open
#9,737 0 comments 0 reactions 1 assignee View on GitHub

Maintainers usually reply within 1 day

@Hectorhammett is already working on this.

Since Sep 25, 2026.

Assessment

This issue has not been assessed yet.

Description

Result::rows() can retry UNAVAILABLE errors forever, when the server keeps returning UNAVAILABLE after the first stream is interrupted. The retry limit from RetrySettings (default 3) is never applied.

This issue is a bit hard to explain but here goes...

The bit of code that needs fixing is here.
https://github.com/googleapis/google-cloud-php/blob/c891a48bd3bd3f132dd7bc3bc35ff73844743abb/Spanner/src/Result.php#L182

This block is called when a ServiceException is thrown with status UNAVAILABLE while the Generator returned from $call is iterating. I think the expected behavior here is to re-execute the $call, reconnect and resume the iterating process. At first glance it seemed like it's doing exactly that.
But when I actually run it, I noticed that when $call is actually invoked in ExponentialBackoff::execute($call, ...), it's just returning the Generator that is not started (see below).

https://github.com/googleapis/google-cloud-php/blob/c891a48bd3bd3f132dd7bc3bc35ff73844743abb/Core/src/ExponentialBackoff.php#L97

Since the code inside the $call is not executed, the unstarted generator gets incorrectly assigned and the loop is continued. When $this->generator->current() is called again (Result.php:L138), and if another ServiceException (with status UNAVAILABLE) is thrown again, the whole process is repeated.

I think the expected behavior here is to have the generator start when $backoff->execute(...) is run so that backoff can actually be applied.

Result::createGenerator(...) run with a similar logic, but there the generator is started inside the callback so it runs correctly like so...

https://github.com/googleapis/google-cloud-php/blob/c891a48bd3bd3f132dd7bc3bc35ff73844743abb/Spanner/src/Result.php#L480-L483

So I think this can be fixed by applying by changing...

$this->generator = $backoff->execute($call, [$this->resumeToken, $this->transaction()]);

to

$this->generator = $backoff->execute(function () use ($call) {
    $generator = $call();
    $generator->valid();
    return $generator;
});
Environment details
  • OS: Alpine Linux
  • PHP version: 8.5.10
  • Package name and version: google/cloud-spanner v2.11.0
Steps to reproduce
  1. Run a large query using Database::execute(...)
  2. Call rows()
  3. Start iterating.
  4. Network disconnects and throw UNAVAILABLE midway.
Dominant language
PHP
Stars
1.2k
Forks
464
Avg merge
1d 23h
Merged PRs (30d)
81

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from googleapis/google-cloud-php

All issues in googleapis/google-cloud-php

Similar issues

More PHP issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.