nextcloud/all-in-one · critical · \Exception

Could not pull image {imageName} (attempt {attempt}/{maxRetr

Error message

Could not pull image {imageName} (attempt {attempt}/{maxRetries}): {errorDetails}

What it means

The pull loop (maxRetries = 3, 1s sleep between attempts, streaming POST images/create with per-line error events) exhausted all attempts and the image was confirmed absent locally beforehand (GET images/{name}/json failed), so the last error is thrown with attempt count and details. If the image WAS already present locally, the failure is only logged via error_log and the method continues — the exception means there is no local fallback.

Source

Thrown at php/src/Docker/DockerActionManager.php:616

                        $interval = time() - $lastHeartbeat;
                        if ($interval >= self::PULL_HEARTBEAT_INTERVAL_SECONDS) {
                            $addToStreamingResponseBody(".", $container);
                            $lastHeartbeat = $now;
                        }
                    }
                }
                if ($pullErrors !== []) {
                    throw new \Exception(implode('; ', $pullErrors));
                }
                break;
            } catch (\Exception $e) {
                $errorDetails = $e instanceof RequestException
                    ? $e->getResponse()?->getBody()->getContents()
                    : $e->getMessage();
                $message = "Could not pull image " . $imageName . " (attempt $attempt/$maxRetries): " . $errorDetails;
                if ($attempt === $maxRetries) {
                    if ($imageIsThere === false) {
                        throw new \Exception($message);
                    } else {
                        error_log($message);
                    }
                } else {
                    error_log($message . ' Retrying...');
                    sleep(1);
                }
            }
        }
    }

    private function isContainerUpdateAvailable(string $id): string {
        $container = $this->containerDefinitionFetcher->GetContainerById($id);

        $updateAvailable = "";
        if ($container->GetUpdateState() === VersionState::Different) {
            $updateAvailable = '1';
        }

View on GitHub (pinned to 6b788eec5e)

Solutions

  1. Pull manually on the host: docker pull <imageName> to see the daemon's full error
  2. On 429 toomanyrequests: wait the quota window or docker login (authenticated limits are higher), or configure a registry mirror
  3. Verify the tag actually exists in the registry before deploying
  4. Check DNS/egress from the docker host to the registry and retry once fixed

Example fix

// before: hard fail after 3 attempts
// after: caller-level backoff with jitter before giving up
$attempts = [5, 30, 120];
foreach ($attempts as $i => $delay) {
    try {
        $docker->PullImage($container, $stream);
        break;
    } catch (\Exception $e) {
        if ($i === count($attempts) - 1) { throw $e; }
        error_log('Pull failed, retrying in ' . $delay . 's: ' . $e->getMessage());
        sleep($delay);
    }
}
Defensive patterns

Strategy: retry

Validate before calling

// Pre-check local presence so an absent image + failing registry fails fast and clearly
try {
    $docker->sendHttpRequest('GET', $docker->BuildApiUrl('images/' . rawurlencode($imageName) . '/json'));
    $present = true;
} catch (\Throwable) {
    $present = false; // pull is mandatory — ensure egress/quota before continuing
}

Try / catch

// Library already retries 3x internally; caller should retry with LONGER backoff
// (rate-limit windows are minutes, so immediate retries cannot help)
try {
    $docker->PullImage($container, $stream);
} catch (\Exception $e) {
    if (str_contains($e->getMessage(), 'toomanyrequests')) {
        scheduleRetry(15 * 60); // Docker Hub quota window
        return;
    }
    throw $e;
}

Prevention

When it happens

Trigger: Tag or repository does not exist ('manifest unknown'); Docker Hub anonymous pull rate limit (429 toomanyrequests); no route/DNS to the registry; private image without credentials; a transient network error repeating three times; every pull-stream event carried an 'error' key.

Common situations: Docker Hub rate limits on busy or shared-IP hosts; typo'd or not-yet-published AIO channel tag; air-gapped host without a registry mirror; restricted egress blocking registry-1.docker.io.

Related errors


AI-assisted analysis of nextcloud/all-in-one@6b788eec5e (2026-08-21). Data as JSON: /api/errors/9fa38fb94e1e0294. Report an issue: GitHub.