Skip to content

ECRClient.PutImageCommand retag image: ImageAlreadyExistsException #6642

@asdfractal

Description

@asdfractal

Checkboxes for prior research

Describe the bug

Following these steps I'm able to retag an image using AWS CLI
https://docs.aws.amazon.com/AmazonECR/latest/userguide/image-retag.html

Replicating the steps using AWS SDK results in ImageAlreadyExistsException when providing a new tag

Regression Issue

  • Select this option if this issue appears to be a regression.

SDK version number

@aws-sdk/client-ecr@latest (AWS Lambda)

Which JavaScript Runtime is this issue in?

Node.js

Details of the browser/Node.js/ReactNative version

20.x

Reproduction Steps

I'm sorry, I can't easily provide a copy-able snippet due to private repository. Public isn't working for me and potentially behaves differently.

This is using AWS Lambda. I've tried with and without the digest field.

import { ECRClient, BatchGetImageCommand, PutImageCommand } from "@aws-sdk/client-ecr"

export const handler = async (event) => {
  const client = new ECRClient({});
  const input = { 
    registryId: "[redacted]",
    repositoryName: "[redacted]-app-pr", 
    imageIds: [ 
      { 
        imageTag: "2.0.2024.11.03-[redacted]",
      },
    ],
  };
  const command = new BatchGetImageCommand(input);
  const response = await client.send(command);
  const putInput = {
    registryId: "[redacted]",
    repositoryName: "[redacted]-app-pr",
    imageDigest: response.images[0].imageId.imageDigest,
    imageManifest: response.images[0].imageManifest,
    imageIds: [ 
      { 
        imageTag: "lambda",
      },
    ],
  };
  const putCommand = new PutImageCommand(putInput);
  const putResponse = await client.send(putCommand);
  return putResponse;
};

Response:

{
  "errorType": "ImageAlreadyExistsException",
  "errorMessage": "Image with digest 'sha256:f6f0e106c6b51c6be8218d3ef498c2ceab32dd13d8eace23928c08c1fb14e2b5' already exists in the repository with name '[redacted]-app-pr' in registry with id '[redacted]'",
  "trace": [
    "ImageAlreadyExistsException: Image with digest 'sha256:f6f0e106c6b51c6be8218d3ef498c2ceab32dd13d8eace23928c08c1fb14e2b5' already exists in the repository with name '[redacted]-app-pr' in registry with id '[redacted]'",
    "    at de_ImageAlreadyExistsExceptionRes (/var/runtime/node_modules/@aws-sdk/client-ecr/dist-cjs/index.js:2176:21)",
    "    at de_CommandError (/var/runtime/node_modules/@aws-sdk/client-ecr/dist-cjs/index.js:2136:19)",
    "    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)",
    "    at async /var/runtime/node_modules/@aws-sdk/node_modules/@smithy/middleware-serde/dist-cjs/index.js:35:20",
    "    at async /var/runtime/node_modules/@aws-sdk/node_modules/@smithy/core/dist-cjs/index.js:165:18",
    "    at async /var/runtime/node_modules/@aws-sdk/node_modules/@smithy/middleware-retry/dist-cjs/index.js:320:38",
    "    at async /var/runtime/node_modules/@aws-sdk/middleware-logger/dist-cjs/index.js:34:22",
    "    at async Runtime.handler (file:///var/task/index.mjs:37:23)"
  ]
}

AWS CLI

MANIFEST=$(aws ecr batch-get-image --repository-name [redacted]-app-pr --image-ids imageTag=2.0.2024.11.03-[redacted] --output text --query 'images[].imageManifest')
aws ecr put-image --repository-name [redacted]-app-pr --image-tag awscliput --image-manifest "$MANIFEST"

{
    "image": {
        "registryId": "[redacted]",
        "repositoryName": "[redacted]-app-pr",
        "imageId": {
            "imageDigest": "sha256:f6f0e106c6b51c6be8218d3ef498c2ceab32dd13d8eace23928c08c1fb14e2b5",
            "imageTag": "awscliput"
        },
        "imageManifest": "{\n   \"schemaVersion\": 2,\n   \"mediaType\": \"application/vnd.docker.distribution.manifest.v2+json\",\n   \"config\": {\n      \"mediaType\": \"application/vnd.docker.container.image.v1+json\",\n      \"size\": 1568,\n      \"digest\": \"sha256:154148336df37dcc4c8a36d0fb0c254bc78b40722adb6a3bb68b4137b3d7aa6b\"\n   },\n   \"layers\": [\n      {\n         \"mediaType\": \"application/vnd.docker.image.rootfs.diff.tar.gzip\",\n         \"size\": 52238109,\n         \"digest\": \"sha256:592fcbe9ebcec6e31ad10b3d219e4f61ce8e39180e215fab37ae75bc7ac4c0b7\"\n      },\n      {\n         \"mediaType\": \"application/vnd.docker.image.rootfs.diff.tar.gzip\",\n         \"size\": 254447733,\n         \"digest\": \"sha256:7f68c3d55775177fb1bd69875de610fb481f5a953f395c414ccbd391c5839e2b\"\n      }\n   ]\n}",
        "imageManifestMediaType": "application/vnd.docker.distribution.manifest.v2+json"
    }
}

aws ecr batch-get-image --repository-name [redacted]-app-pr --image-ids imageDigest=sha256:f6f0e106c6b51c6be8218d3ef498c2ceab32dd13d8eace23928c08c1fb14e2b5

{
    "images": [
        {
            "registryId": "[redacted]",
            "repositoryName": "[redacted]-app-pr",
            "imageId": {
                "imageDigest": "sha256:f6f0e106c6b51c6be8218d3ef498c2ceab32dd13d8eace23928c08c1fb14e2b5",
                "imageTag": "2.0.2024.11.03-[redacted]"
            },
            "imageManifest": "{\n   \"schemaVersion\": 2,\n   \"mediaType\": \"application/vnd.docker.distribution.manifest.v2+json\",\n   \"config\": {\n      \"mediaType\": \"application/vnd.docker.container.image.v1+json\",\n      \"size\": 1568,\n      \"digest\": \"sha256:154148336df37dcc4c8a36d0fb0c254bc78b40722adb6a3bb68b4137b3d7aa6b\"\n   },\n   \"layers\": [\n      {\n         \"mediaType\": \"application/vnd.docker.image.rootfs.diff.tar.gzip\",\n         \"size\": 52238109,\n         \"digest\": \"sha256:592fcbe9ebcec6e31ad10b3d219e4f61ce8e39180e215fab37ae75bc7ac4c0b7\"\n      },\n      {\n         \"mediaType\": \"application/vnd.docker.image.rootfs.diff.tar.gzip\",\n         \"size\": 254447733,\n         \"digest\": \"sha256:7f68c3d55775177fb1bd69875de610fb481f5a953f395c414ccbd391c5839e2b\"\n      }\n   ]\n}",
            "imageManifestMediaType": "application/vnd.docker.distribution.manifest.v2+json"
        },
        {
            "registryId": "[redacted]",
            "repositoryName": "[redacted]-app-pr",
            "imageId": {
                "imageDigest": "sha256:f6f0e106c6b51c6be8218d3ef498c2ceab32dd13d8eace23928c08c1fb14e2b5",
                "imageTag": "awscliput"
            },
            "imageManifest": "{\n   \"schemaVersion\": 2,\n   \"mediaType\": \"application/vnd.docker.distribution.manifest.v2+json\",\n   \"config\": {\n      \"mediaType\": \"application/vnd.docker.container.image.v1+json\",\n      \"size\": 1568,\n      \"digest\": \"sha256:154148336df37dcc4c8a36d0fb0c254bc78b40722adb6a3bb68b4137b3d7aa6b\"\n   },\n   \"layers\": [\n      {\n         \"mediaType\": \"application/vnd.docker.image.rootfs.diff.tar.gzip\",\n         \"size\": 52238109,\n         \"digest\": \"sha256:592fcbe9ebcec6e31ad10b3d219e4f61ce8e39180e215fab37ae75bc7ac4c0b7\"\n      },\n      {\n         \"mediaType\": \"application/vnd.docker.image.rootfs.diff.tar.gzip\",\n         \"size\": 254447733,\n         \"digest\": \"sha256:7f68c3d55775177fb1bd69875de610fb481f5a953f395c414ccbd391c5839e2b\"\n      }\n   ]\n}",
            "imageManifestMediaType": "application/vnd.docker.distribution.manifest.v2+json"
        }
    ],
    "failures": []
}

Observed Behavior

Using Lambda/SDK - ImageAlreadyExistsException when providing a new tag
Using CLI - Existing image is tagged with new tag

Expected Behavior

Using Lambda/SDK - Existing image is tagged with new tag

Possible Solution

No response

Additional Information/Context

In SDK, I've tried playing around with processing the manifest through JSON parse/stringify to see if anything changed.
This results in either:
SerializationException (parse only)
ImageDigestDoesNotMatchException (parse then stringify)

I believe using the manifest response directly is correct and the issue is the command is not correctly identifying that there is a new tag provided.

Metadata

Metadata

Assignees

Labels

bugThis issue is a bug.p2This is a standard priority issueresponse-requestedWaiting on additional info and feedback. Will move to \"closing-soon\" in 7 days.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions