diff --git a/moto/s3/exceptions.py b/moto/s3/exceptions.py
index ba7b09429..6633c62d3 100644
--- a/moto/s3/exceptions.py
+++ b/moto/s3/exceptions.py
@@ -1,2 +1,6 @@
 class BucketAlreadyExists(Exception):
     pass
+
+
+class MissingBucket(Exception):
+    pass
diff --git a/moto/s3/models.py b/moto/s3/models.py
index 67b40d5e0..b224fbe21 100644
--- a/moto/s3/models.py
+++ b/moto/s3/models.py
@@ -7,7 +7,7 @@ import itertools
 
 from moto.core import BaseBackend
 from moto.core.utils import iso_8601_datetime, rfc_1123_datetime
-from .exceptions import BucketAlreadyExists
+from .exceptions import BucketAlreadyExists, MissingBucket
 from .utils import clean_key_name, _VersionedKeyStore
 
 UPLOAD_ID_BYTES = 43
@@ -177,40 +177,42 @@ class S3Backend(BaseBackend):
         return self.buckets.values()
 
     def get_bucket(self, bucket_name):
-        return self.buckets.get(bucket_name)
+        try:
+            return self.buckets[bucket_name]
+        except KeyError:
+            raise MissingBucket()
 
     def delete_bucket(self, bucket_name):
-        bucket = self.buckets.get(bucket_name)
-        if bucket:
-            if bucket.keys:
-                # Can't delete a bucket with keys
-                return False
-            else:
-                return self.buckets.pop(bucket_name)
-        return None
+        bucket = self.get_bucket(bucket_name)
+        if bucket.keys:
+            # Can't delete a bucket with keys
+            return False
+        else:
+            return self.buckets.pop(bucket_name)
 
     def set_bucket_versioning(self, bucket_name, status):
-        self.buckets[bucket_name].versioning_status = status
+        self.get_bucket(bucket_name).versioning_status = status
 
     def get_bucket_versioning(self, bucket_name):
-        return self.buckets[bucket_name].versioning_status
+        return self.get_bucket(bucket_name).versioning_status
 
     def get_bucket_versions(self, bucket_name, delimiter=None,
                             encoding_type=None,
                             key_marker=None,
                             max_keys=None,
                             version_id_marker=None):
-        bucket = self.buckets[bucket_name]
+        bucket = self.get_bucket(bucket_name)
 
         if any((delimiter, encoding_type, key_marker, version_id_marker)):
             raise NotImplementedError(
                 "Called get_bucket_versions with some of delimiter, encoding_type, key_marker, version_id_marker")
 
         return itertools.chain(*(l for _, l in bucket.keys.iterlists()))
+
     def set_key(self, bucket_name, key_name, value, storage=None, etag=None):
         key_name = clean_key_name(key_name)
 
-        bucket = self.buckets[bucket_name]
+        bucket = self.get_bucket(bucket_name)
 
         old_key = bucket.keys.get(key_name, None)
         if old_key is not None and bucket.is_versioned:
@@ -248,14 +250,14 @@ class S3Backend(BaseBackend):
                         return key
 
     def initiate_multipart(self, bucket_name, key_name):
-        bucket = self.buckets[bucket_name]
+        bucket = self.get_bucket(bucket_name)
         new_multipart = FakeMultipart(key_name)
         bucket.multiparts[new_multipart.id] = new_multipart
 
         return new_multipart
 
     def complete_multipart(self, bucket_name, multipart_id):
-        bucket = self.buckets[bucket_name]
+        bucket = self.get_bucket(bucket_name)
         multipart = bucket.multiparts[multipart_id]
         value, etag = multipart.complete()
         if value is None:
@@ -265,27 +267,27 @@ class S3Backend(BaseBackend):
         return self.set_key(bucket_name, multipart.key_name, value, etag=etag)
 
     def cancel_multipart(self, bucket_name, multipart_id):
-        bucket = self.buckets[bucket_name]
+        bucket = self.get_bucket(bucket_name)
         del bucket.multiparts[multipart_id]
 
     def list_multipart(self, bucket_name, multipart_id):
-        bucket = self.buckets[bucket_name]
+        bucket = self.get_bucket(bucket_name)
         return bucket.multiparts[multipart_id].list_parts()
 
     def get_all_multiparts(self, bucket_name):
-        bucket = self.buckets[bucket_name]
+        bucket = self.get_bucket(bucket_name)
         return bucket.multiparts
 
     def set_part(self, bucket_name, multipart_id, part_id, value):
-        bucket = self.buckets[bucket_name]
+        bucket = self.get_bucket(bucket_name)
         multipart = bucket.multiparts[multipart_id]
         return multipart.set_part(part_id, value)
 
     def copy_part(self, dest_bucket_name, multipart_id, part_id,
                   src_bucket_name, src_key_name):
         src_key_name = clean_key_name(src_key_name)
-        src_bucket = self.buckets[src_bucket_name]
-        dest_bucket = self.buckets[dest_bucket_name]
+        src_bucket = self.get_bucket(src_bucket_name)
+        dest_bucket = self.get_bucket(dest_bucket_name)
         multipart = dest_bucket.multiparts[multipart_id]
         return multipart.set_part(part_id, src_bucket.keys[src_key_name].value)
 
@@ -317,14 +319,14 @@ class S3Backend(BaseBackend):
 
     def delete_key(self, bucket_name, key_name):
         key_name = clean_key_name(key_name)
-        bucket = self.buckets[bucket_name]
+        bucket = self.get_bucket(bucket_name)
         return bucket.keys.pop(key_name)
 
     def copy_key(self, src_bucket_name, src_key_name, dest_bucket_name, dest_key_name, storage=None):
         src_key_name = clean_key_name(src_key_name)
         dest_key_name = clean_key_name(dest_key_name)
-        src_bucket = self.buckets[src_bucket_name]
-        dest_bucket = self.buckets[dest_bucket_name]
+        src_bucket = self.get_bucket(src_bucket_name)
+        dest_bucket = self.get_bucket(dest_bucket_name)
         key = src_bucket.keys[src_key_name]
         if dest_key_name != src_key_name:
             key = key.copy(dest_key_name)
diff --git a/moto/s3/responses.py b/moto/s3/responses.py
index 9e657430f..eee8e22de 100644
--- a/moto/s3/responses.py
+++ b/moto/s3/responses.py
@@ -3,7 +3,7 @@ import re
 
 from jinja2 import Template
 
-from .exceptions import BucketAlreadyExists
+from .exceptions import BucketAlreadyExists, MissingBucket
 from .models import s3_backend
 from .utils import bucket_name_from_url
 from xml.dom import minidom
@@ -26,7 +26,11 @@ class ResponseObject(object):
         return template.render(buckets=all_buckets)
 
     def bucket_response(self, request, full_url, headers):
-        response = self._bucket_response(request, full_url, headers)
+        try:
+            response = self._bucket_response(request, full_url, headers)
+        except MissingBucket:
+            return 404, headers, ""
+
         if isinstance(response, basestring):
             return 200, headers, response
         else:
@@ -57,11 +61,12 @@ class ResponseObject(object):
             raise NotImplementedError("Method {0} has not been impelemented in the S3 backend yet".format(method))
 
     def _bucket_response_head(self, bucket_name, headers):
-        bucket = self.backend.get_bucket(bucket_name)
-        if bucket:
-            return 200, headers, ""
-        else:
+        try:
+            self.backend.get_bucket(bucket_name)
+        except MissingBucket:
             return 404, headers, ""
+        else:
+            return 200, headers, ""
 
     def _bucket_response_get(self, bucket_name, querystring, headers):
         if 'uploads' in querystring:
@@ -104,22 +109,23 @@ class ResponseObject(object):
                 is_truncated='false',
             )
 
-        bucket = self.backend.get_bucket(bucket_name)
-        if bucket:
-            prefix = querystring.get('prefix', [None])[0]
-            delimiter = querystring.get('delimiter', [None])[0]
-            result_keys, result_folders = self.backend.prefix_query(bucket, prefix, delimiter)
-            template = Template(S3_BUCKET_GET_RESPONSE)
-            return 200, headers, template.render(
-                bucket=bucket,
-                prefix=prefix,
-                delimiter=delimiter,
-                result_keys=result_keys,
-                result_folders=result_folders
-            )
-        else:
+        try:
+            bucket = self.backend.get_bucket(bucket_name)
+        except MissingBucket:
             return 404, headers, ""
 
+        prefix = querystring.get('prefix', [None])[0]
+        delimiter = querystring.get('delimiter', [None])[0]
+        result_keys, result_folders = self.backend.prefix_query(bucket, prefix, delimiter)
+        template = Template(S3_BUCKET_GET_RESPONSE)
+        return 200, headers, template.render(
+            bucket=bucket,
+            prefix=prefix,
+            delimiter=delimiter,
+            result_keys=result_keys,
+            result_folders=result_folders
+        )
+
     def _bucket_response_put(self, request, bucket_name, querystring, headers):
         if 'versioning' in querystring:
             ver = re.search('([A-Za-z]+)', request.body)
@@ -138,12 +144,14 @@ class ResponseObject(object):
             return 200, headers, template.render(bucket=new_bucket)
 
     def _bucket_response_delete(self, bucket_name, headers):
-        removed_bucket = self.backend.delete_bucket(bucket_name)
-        if removed_bucket is None:
+        try:
+            removed_bucket = self.backend.delete_bucket(bucket_name)
+        except MissingBucket:
             # Non-existant bucket
             template = Template(S3_DELETE_NON_EXISTING_BUCKET)
             return 404, headers, template.render(bucket_name=bucket_name)
-        elif removed_bucket:
+
+        if removed_bucket:
             # Bucket exists
             template = Template(S3_DELETE_BUCKET_SUCCESS)
             return 204, headers, template.render(bucket=removed_bucket)
@@ -198,13 +206,17 @@ class ResponseObject(object):
                 key_name = k.firstChild.nodeValue
                 self.backend.delete_key(bucket_name, key_name)
                 deleted_names.append(key_name)
-            except KeyError as e:
+            except KeyError:
                 error_names.append(key_name)
 
-        return 200, headers, template.render(deleted=deleted_names,delete_errors=error_names)
+        return 200, headers, template.render(deleted=deleted_names, delete_errors=error_names)
 
     def key_response(self, request, full_url, headers):
-        response = self._key_response(request, full_url, headers)
+        try:
+            response = self._key_response(request, full_url, headers)
+        except MissingBucket:
+            return 404, headers, ""
+
         if isinstance(response, basestring):
             return 200, headers, response
         else:
@@ -455,43 +467,43 @@ S3_DELETE_BUCKET_WITH_ITEMS_ERROR = """
 S3_BUCKET_VERSIONING = """
 
 
-	{{ bucket_versioning_status }}
+    {{ bucket_versioning_status }}
 
 """
 
 S3_BUCKET_GET_VERSIONING = """
 
 {% if status is none %}
-	
+    
 {% else %}
-	
-	{{ status }}
-	
+    
+    {{ status }}
+    
 {% endif %}
 """
 
 S3_BUCKET_GET_VERSIONS = """
 
-	{{ bucket.name }}
-	{{ prefix }}
-	{{ key_marker }}
-	{{ max_keys }}
-	{{ is_truncated }}
-	{% for key in key_list %}
-	
-		{{ key.name }}
-		{{ key._version_id }}
-		false
-		{{ key.last_modified_ISO8601 }}
-		{{ key.etag }}
-		{{ key.size }}
-		{{ key.storage_class }}
-		
-			75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a
-			webfile
-		
-	
-	{% endfor %}
+    {{ bucket.name }}
+    {{ prefix }}
+    {{ key_marker }}
+    {{ max_keys }}
+    {{ is_truncated }}
+    {% for key in key_list %}
+    
+        {{ key.name }}
+        {{ key._version_id }}
+        false
+        {{ key.last_modified_ISO8601 }}
+        {{ key.etag }}
+        {{ key.size }}
+        {{ key.storage_class }}
+        
+            75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a
+            webfile
+        
+    
+    {% endfor %}
 
 """
 
diff --git a/tests/test_s3/test_s3.py b/tests/test_s3/test_s3.py
index 5f08f30cd..1738db53f 100644
--- a/tests/test_s3/test_s3.py
+++ b/tests/test_s3/test_s3.py
@@ -149,6 +149,16 @@ def test_list_multiparts():
     uploads.should.be.empty
 
 
+@mock_s3
+def test_key_save_to_missing_bucket():
+    conn = boto.connect_s3('the_key', 'the_secret')
+    bucket = conn.get_bucket('mybucket', validate=False)
+
+    key = Key(bucket)
+    key.key = "the-key"
+    key.set_contents_from_string.when.called_with("foobar").should.throw(S3ResponseError)
+
+
 @mock_s3
 def test_missing_key():
     conn = boto.connect_s3('the_key', 'the_secret')