title: Heroku Internal Server Error. ParamValidationError. Invalid bucket name "": Python/Django
body: <p>absolute beginner here having an absolute nightmare deploying a tiny website to Heroku. I have worked through numerous issues to get to this point, but I now seem to have hit another wall. I have raised this as a support ticket with Heroku, but unless it is an issue on their side I doubt whether they will come back to me with a clear answer.</p>
  
  <p>I can successfully deploy to Heroku, however, when opening up my web app I can only see the words "Internal Server Error" in place of my site. I receive an issue/error through to my Sentry log, which is as follows:</p>
  
  <pre><code>MESSAGE
  ParamValidationError: Parameter validation failed:
  Invalid bucket name "": Bucket name must match the regex "^[a-zA-Z0-9.\-_]{1,255}$"
  EXCEPTION(most recent call first)App OnlyFullRaw
  ParamValidationError
  Parameter validation failed:
  Invalid bucket name "": Bucket name must match the regex "^[a-zA-Z0-9.\-_]{1,255}$"
  storages/backends/s3boto3.py in exists at line 478
      def exists(self, name):
          name = self._normalize_name(self._clean_name(name))
          if self.entries:
              return name in self.entries
          try:
              self.connection.meta.client.head_object(Bucket=self.bucket_name, Key=name)
              return True
          except ClientError:
              return False
      def listdir(self, name):
  name    
  'CACHE/css/cf136be60f95.css'
  self    
  &lt;storages.backends.s3boto3.S3Boto3Storage object at 0x7fbe4b7f4e80&gt;
  compressor/base.py in output_file at line 321
          """
          The output method that saves the content to a file and renders
          the appropriate template with the file's URL.
          """
          new_filepath = self.get_filepath(content, basename=basename)
          if not self.storage.exists(new_filepath) or forced:
              self.storage.save(new_filepath, ContentFile(content.encode(self.charset)))
          url = mark_safe(self.storage.url(new_filepath))
          return self.render_output(mode, {"url": url})
      def output_inline(self, mode, content, forced=False, basename=None):
  basename    
  None
  content 
  '/*!
   * Material Design for Bootstrap 4
   * Version: MDB Free 4.4.5
   *
   *
   * Copyright: Material Design for Bootstrap
   * https://mdbootstrap.com/
   *
   * Read the license: https://mdbootstrap.com/license/
   *
   *
   * Documentation: https://mdbootstrap.com/
   *
   * Getting started: https://mdbootstrap.com/getting-started/
   *
   * Tutorials: https://mdbootstrap.com/bootstrap-tutorial/
   *
   * Templates: https://'
  forced  
  False
  mode    
  'file'
  new_filepath    
  'CACHE/css/cf136be60f95.css'
  self    
  &lt;compressor.css.CssCompressor object at 0x7fbe4aadf240&gt;
  compressor/base.py in handle_output at line 310
      def handle_output(self, mode, content, forced, basename=None):
          # Then check for the appropriate output method and call it
          output_func = getattr(self, "output_%s" % mode, None)
          if callable(output_func):
              return output_func(mode, content, forced, basename)
          # Total failure, raise a general exception
          raise CompressorError(
              "Couldn't find output method for mode '%s'" % mode)
      def output_file(self, mode, content, forced=False, basename=None):
  basename    
  None
  content 
  '/*!
   * Material Design for Bootstrap 4
   * Version: MDB Free 4.4.5
   *
   *
   * Copyright: Material Design for Bootstrap
   * https://mdbootstrap.com/
   *
   * Read the license: https://mdbootstrap.com/license/
   *
   *
   * Documentation: https://mdbootstrap.com/
   *
   * Getting started: https://mdbootstrap.com/getting-started/
   *
   * Tutorials: https://mdbootstrap.com/bootstrap-tutorial/
   *
   * Templates: https://'
  forced  
  False
  mode    
  'file'
  output_func 
  &lt;bound method Compressor.output_file of &lt;compressor.css.CssCompressor object at 0x7fbe4aadf240&gt;&gt;
  self    
  &lt;compressor.css.CssCompressor object at 0x7fbe4aadf240&gt;
  compressor/base.py in output at line 302
          if not output:
              return ''
          if settings.COMPRESS_ENABLED or forced:
              filtered_output = self.filter_output(output)
              return self.handle_output(mode, filtered_output, forced)
          return output
      def handle_output(self, mode, content, forced, basename=None):
          # Then check for the appropriate output method and call it
  filtered_output 
  '/*!
   * Material Design for Bootstrap 4
   * Version: MDB Free 4.4.5
   *
   *
   * Copyright: Material Design for Bootstrap
   * https://mdbootstrap.com/
   *
   * Read the license: https://mdbootstrap.com/license/
   *
   *
   * Documentation: https://mdbootstrap.com/
   *
   * Getting started: https://mdbootstrap.com/getting-started/
   *
   * Tutorials: https://mdbootstrap.com/bootstrap-tutorial/
   *
   * Templates: https://'
  forced  
  False
  mode    
  'file'
  output  
  '/*!
   * Material Design for Bootstrap 4
   * Version: MDB Free 4.4.5
   *
   *
   * Copyright: Material Design for Bootstrap
   * https://mdbootstrap.com/
   *
   * Read the license: https://mdbootstrap.com/license/
   *
   *
   * Documentation: https://mdbootstrap.com/
   *
   * Getting started: https://mdbootstrap.com/getting-started/
   *
   * Tutorials: https://mdbootstrap.com/bootstrap-tutorial/
   *
   * Templates: https://'
  self    
  &lt;compressor.css.CssCompressor object at 0x7fbe4aadf240&gt;
  compressor/css.py in output at line 51
                  ret = []
                  for media, subnode in self.media_nodes:
                      subnode.extra_context.update({'media': media})
                      ret.append(subnode.output(*args, **kwargs))
                  return ''.join(ret)
          return super(CssCompressor, self).output(*args, **kwargs)
  __class__   
  &lt;class 'compressor.css.CssCompressor'&gt;
  args    
  [
  'file'
  ]
  kwargs  
  {
  'forced': False
  }
  self    
  &lt;compressor.css.CssCompressor object at 0x7fbe4aadf240&gt;
  compressor/css.py in output at line 49
                      ret.append(subnode.output(*args, **kwargs))
  compressor/templatetags/compress.py in render_compressed at line 107
          rendered_output = compressor.output(mode, forced=forced)
  compressor/templatetags/compress.py in render at line 131
          return self.render_compressed(context, self.kind, self.mode, forced=forced)
  Called from: django/template/base.py in render_annotated
  </code></pre>
  
  <p>I have used django-cookiecuttter as the base template for my site. Only yesterday I read a separate issue raised against django-cookiecutter for another <a href="https://github.com/pydanny/cookiecutter-django/issues/1527" rel="nofollow noreferrer">Internal Server Error issue</a> which I hoped may help me too (even though the details appeared different), but I have tried removal of "min" from the css file without success.</p>
  
  <p>As the error message mentions storage and compressor, is it possible that this is Django-compressor related or whitenoise (I have both installed)? I have looked into trying to compile offline looking the instructions <a href="https://github.com/django-compressor/django-compressor/issues/486" rel="nofollow noreferrer">here</a>, but this might be out of date by now and as my site is working well locally I want to avoid unnecessary coding if I can help it. Assistance would be greatly appreciated.</p>
  
  <p>I am using windows with Python 3.6.2 and Django 2.0.2. My production static settings are as follows:</p>
  
  <pre><code># Static Assets
  # ------------------------
  STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
  
  # COMPRESSOR
  # ------------------------------------------------------------------------------
  COMPRESS_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
  COMPRESS_URL = STATIC_URL
  COMPRESS_ENABLED = env.bool('COMPRESS_ENABLED', default=True)
  </code></pre>
  
  <p>Thanks in advance.</p>
  
  <p>UPDATE: </p>
  
  <p>I still see the Internal Server Error, however, I'm sure this relates to the way I have set up my bucket. I have followed this <a href="https://www.caktusgroup.com/blog/2014/11/10/Using-Amazon-S3-to-store-your-Django-sites-static-and-media-files/" rel="nofollow noreferrer">tutorial</a> adding the IAM group and policy, but I must be doing something wrong because I get an improperly configured error message with the following details:</p>
  
  <pre><code>Client error:An error occurred (403) when calling the HeadBucket operation: Forbidden
  </code></pre>
  
  <p>My policy in AWS is as follows (of which I have tried a few iterations of):</p>
  
  <pre><code>{
      "Version": "2012-10-17",
      "Statement": [
          {
              "Sid": "VisualEditor0",
              "Effect": "Allow",
              "Action": [
                  "s3:ListAllMyBuckets",
                  "s3:HeadBucket",
                  "s3:ListObjects"
              ],
              "Resource": "*"
          },
          {
              "Sid": "VisualEditor1",
              "Effect": "Allow",
              "Action": "s3:*",
              "Resource": [
                  "arn:aws:s3:::mybucket/*",
                  "arn:aws:s3:::mybucket"
              ]
          }
      ]
  }
  </code></pre>
  
  <p>I'm quickly running out of hair as I seem to be pulling it out at an alarming rate. No doubt this is yet another schoolboy error, so appreciate your time in reviewing.</p>