GoogleContainerTools/jib · error · IllegalStateException

push may fail with pull-only bearer auth token

Error message

push may fail with pull-only bearer auth token

What it means

RegistryClient.pushManifest refuses to push a manifest when the client is using Bearer authentication with a token that was obtained with pull-only (read-only) scopes. Since the token lacks push scope, the push would fail at the registry, so Jib fails fast with IllegalStateException.

Source

Thrown at jib-core/src/main/java/com/google/cloud/tools/jib/registry/RegistryClient.java:454

  public ManifestAndDigest<ManifestTemplate> pullManifest(String imageQualifier)
      throws IOException, RegistryException {
    return pullManifest(imageQualifier, ManifestTemplate.class);
  }

  /**
   * Pushes the image manifest for a specific tag.
   *
   * @param manifestTemplate the image manifest
   * @param imageTag the tag to push on
   * @return the digest of the pushed image
   * @throws IOException if communicating with the endpoint fails
   * @throws RegistryException if communicating with the endpoint fails
   */
  public DescriptorDigest pushManifest(ManifestTemplate manifestTemplate, String imageTag)
      throws IOException, RegistryException {
    if (isBearerAuth(authorization.get()) && readOnlyBearerAuth) {
      throw new IllegalStateException("push may fail with pull-only bearer auth token");
    }

    return callRegistryEndpoint(
        new ManifestPusher(
            registryEndpointRequestProperties, manifestTemplate, imageTag, eventHandlers));
  }

  /**
   * Check if a blob is on the registry.
   *
   * @param blobDigest the blob digest to check for
   * @return the BLOB's {@link BlobDescriptor} if the BLOB exists on the registry, or {@link
   *     Optional#empty()} if it doesn't
   * @throws IOException if communicating with the endpoint fails
   * @throws RegistryException if communicating with the endpoint fails
   */
  public Optional<BlobDescriptor> checkBlob(DescriptorDigest blobDigest)
      throws IOException, RegistryException {

View on GitHub (pinned to fb949e2676)

Solutions

  1. Obtain a RegistryClient via a factory that requests push scopes (e.g., RegistryClient.factory(...).setCredential... / toOtherRepository with push intent) so the token is requested with pull,push scope
  2. Use credentials/token with push permissions (service account or IAM role granting write)
  3. If you only intend to pull, do not call pushManifest on this client

Example fix

// before: read-only client used for push
RegistryClient client = new RegistryClient(credential, serverUrl, imageName, eventHandlers);
client.configureReadOnlyBearerAuth();
client.pushManifest(manifest, tag);
// after: client authorized for push
RegistryClient client = new RegistryClient(credential, serverUrl, imageName, eventHandlers); // token fetched with push scope
client.pushManifest(manifest, tag);
Defensive patterns

Strategy: validation

Validate before calling

// ensure the token has push scope before attempting a push
// (Jib guards this internally; pre-validate your service account's scopes in CI)
assertPushScopeGranted(registry, serviceAccount);

Try / catch

try { client.pushManifest(manifest, tag); } catch (IllegalStateException e) { // client is pull-only; obtain a push-scoped client
  newPushScopedClient().pushManifest(manifest, tag); }

Prevention

When it happens

Trigger: Calling pushManifest (or constructing a RegistryClient via factory methods like toOtherRepository) on a client whose authorization is Bearer and readOnlyBearerAuth is true — i.e., the token was fetched without push (pull,push) repository scopes.

Common situations: Building/pushing using a registry client initialized for pulling (e.g., toOtherRegistry/pull-oriented API) and then attempting to push; using an access token scoped read-only; misconfigured service account/token with only pull permissions (e.g., GCR pull-only service account).

Understand the failure class

Background: "You do not have permission" / 403 Forbidden errors: authenticated but not allowed — causes and fixes across open-source libraries — this error's family across 31 libraries.

Related errors


AI-assisted analysis of GoogleContainerTools/jib@fb949e2676 (2026-09-06). Data as JSON: /api/errors/f0dacf68674df3f1. Report an issue: GitHub.