29

This is my boto3 command for getting the object with a specific key from an S3 bucket:

resp = s3client.get_object(Bucket='<>-<>', Key='MzA1MjY1NzkzX2QudHh0')

It gives the following error:

botocore.errorfactory.NoSuchKey: An error occurred (NoSuchKey) when calling the GetObject operation: The specified key does not exist.

I have checked in the bucket, and the key actually exists

enter image description here

Did I miss something or did I do something wrong here?

Community
  • 1
  • 1
Dawny33
  • 10,543
  • 21
  • 82
  • 134

5 Answers5

11

You have a %0A at the end of your URL; that's a line separator.

Chris Pollard
  • 1,625
  • 8
  • 11
  • Yeah. I tried with `MzA1MjY1NzkzX2QudHh0%0A` also. Didn't work :/ – Dawny33 Jun 27 '17 at 11:25
  • Rename your object. That's a special character, probably giving you issues. – Chris Pollard Jun 27 '17 at 11:28
  • 2
    Your bucket has public list too; so I was able to navigate to https://s3.amazonaws.com/cypher-secondarybucket/MzA1MjY1NzkzX2QudHh0%0A and get "Access denied" as opposed to going to https://s3.amazonaws.com/cypher-secondarybucket/MzA1MjY1NzkzX2QudHh0 and getting "Key doesn't exist" – Chris Pollard Jun 27 '17 at 11:31
  • @Dawny33 adding `%0A` to the key will probably result in double-encoding to `%250A`. Add a literal newline `\n` to the key string. And then, like Chris said, rename the key. Special characters will cause grief. – Michael - sqlbot Jun 27 '17 at 12:16
  • [Rectified this](https://www.reddit.com/r/aws/comments/6jrz1j/s3_giving_me_nosuchkey_error_even_when_the_key/djgmfy7/?utm_content=permalink&utm_medium=front&utm_source=reddit&utm_name=aws) :D – Dawny33 Jun 27 '17 at 18:05
8

Since you know the key that you have is definitely in the name of the file you are looking for, I recommend using a filter to get objects with names with your key as their prefix.

s3 = boto3.resource('s3')
bucket = s3.Bucket('cypher-secondarybucket')
for obj in bucket.objects.filter(Prefix='MzA1MjY1NzkzX2QudHh0'):
    print obj.key

When you run this code, you will get the key names of all the files that start with your key. This will help you find out what your file is exactly called on S3.

cookiedough
  • 3,552
  • 2
  • 26
  • 51
7

A generic answer that may useful to those who are thinking about file paths and may be new to the AWS S3 terminology. Not getting the "name" and "key" right will often lead to an exception with the message An error occurred (NoSuchKey)... as posted in this question.

Let's say that you have a JPEG file stored in some "path" in a bucket. Navigating to this object on the AWS console shows the S3 URI to be:

s3://my-bucket/some/very/long/path/my-image.jpeg

You could read the my-image.jpeg object in Python with this basic example:

import boto3

s3client = boto3.client('s3', region_name='us-east-1')

bucket_name = 'my-bucket'
object_key = 'some/very/long/path/my-image.jpeg'

try:
    s3obj = s3client.get_object(Bucket=bucket_name, Key=object_key)
except Exception as e:
    print(f"Error reading key {object_key} from bucket {bucket_name}: {e}")
else:
   print(f"Got object: {s3obj}")
Nagev
  • 10,835
  • 4
  • 58
  • 69
  • 4
    All examples and documentation I had found had a leading `/` at the beginning of the object key. Going by your example and removing the slash finally solved my two-hour struggle with this. – domsson Jun 13 '22 at 06:43
0

Another possible issue that I came across that was causing a line separator in my url for an object was that in one of AWS documentation for getting the key of an object shows this code as an example to get the key of an object.

foreach ($results as $result) {
    foreach ($result['Contents'] as $object) {
        echo $object['Key'] . PHP_EOL;
    }
}

The problem is the PHP_EOL at the end. Just remove it and the line separator goes away.

$object['Key'] . PHP_EOL; --> $object['Key'];

Cesar Bielich
  • 4,754
  • 9
  • 39
  • 81
0
from urllib.parse import unquote
key = "MzA1MjY1NzkzX2QudHh0%0A"

key = unquote(key)

This will remove all special characters from any key.

Tushar Kale
  • 159
  • 1
  • 12