Server 500 error only when deploying to Heroku with DEBUG=False

Here is the broken site & error page:

Abstract Spacecraft

The site works perfectly as it does locally when DEBUG = True. I have an ON_HEROKU=1 config variable set through the Heroku dashboard for the app, which causes the branch in settings.py to set DEBUG = False.

I tried setting it back to DEBUG = True, and everything else the same, and the site then works.

Here is my settings.py:

"""
Django settings for abstract_spacecraft project.

Generated by 'django-admin startproject' using Django 3.1.5.

For more information on this file, see
https://docs.djangoproject.com/en/3.1/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/3.1/ref/settings/
"""

from pathlib import Path
import os
import django_heroku
import dj_database_url

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
SITE_ROOT = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
SETTINGS_PATH = os.path.dirname(os.path.dirname(__file__))

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = os.environ.get('SECRET_KEY', 'TODO: use secret key in deployment')

# SECURITY WARNING: don't run with debug turned on in production!
if os.environ.get('ON_HEROKU', '0') == '0':
    DEBUG = True
else:
    DEBUG = False

# SECURITY WARNING: don't run with debug turned on in production!
#DEBUG = True    # TODO comment out

ALLOWED_HOSTS = [
    'dc166c4c.databases.neo4j.io',
    'abstract-spacecraft.herokuapp.com',
    '127.0.0.1',
]

# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'accounts.apps.AccountsConfig',
    'whitenoise.runserver_nostatic',
    'django_bootstrap5',
    'cd_editor.apps.CdEditorConfig',
    'database.apps.DatabaseConfig',
    'django_neomodel',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'whitenoise.middleware.WhiteNoiseMiddleware',
]

ROOT_URLCONF = 'abstract_spacecraft.urls'

TEMPLATES_PATH = os.path.join(SETTINGS_PATH, 'templates')

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [TEMPLATES_PATH, 
                 os.path.join(TEMPLATES_PATH, 'abstract_spacecraft'),
                 os.path.join(TEMPLATES_PATH, 'accounts'),
                 os.path.join(TEMPLATES_PATH, 'cd_editor'),
                 os.path.join(TEMPLATES_PATH, 'database')],
        'APP_DIRS': True,
        'OPTIONS': {
            'debug': True,
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'abstract_spacecraft.wsgi.application'


# Database
# https://docs.djangoproject.com/en/3.1/ref/settings/#databases

# TODO: try out PostgreSQL in production, i.e. change True to the commented out code;
if os.environ.get('ON_HEROKU', '0') == '0':
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.sqlite3',
            'NAME': BASE_DIR / 'db.sqlite3',
        }
    }
else:
    DATABASES = {
        # TODO: what does this max_age setting do?
        'default' : dj_database_url.config(conn_max_age=600)
    }

# Password validation
# https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/3.1/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.1/howto/static-files/

STATIC_URL = '/static/'
STATICFILES_DIRS = (
  os.path.join(SITE_ROOT, 'static/'),)
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'

def neo4j_url():
    url = os.environ.get('NEO4J_SCHEMA', 'bolt') + "://"
    url += os.environ.get('NEO4J_USERNAME', 'neo4j') + ":"
    url += os.environ.get('NEO4J_PASSWORD', 'fusion123') + "@"
    url += os.environ.get('NEO4J_HOST', 'localhost') + ":"
    url += os.environ.get('NEO4J_PORT', '7687')
    return url

NEOMODEL_NEO4J_BOLT_URL = neo4j_url()

NEOMODEL_SIGNALS = True
NEOMODEL_FORCE_TIMEZONE = False
NEOMODEL_ENCRYPTED_CONNECTION = False  # TODO: how do we switch this on without error?

from neomodel import config   # BUGFIX: had to do it this way
config.MAX_POOL_SIZE = 50  # TODO: what does this affect?

#LOGIN_REDIRECT_URL = 'home'
#LOGOUT_REDIRECT_URL = 'home'

# TODO: Enable Click-jacking protection
X_FRAME_OPTIONS = 'ALLOW'   # ie set this to "DENY"
# https://docs.djangoproject.com/en/1.11/ref/clickjacking/

MAX_TEXT_LENGTH = 80
MAX_USERNAME_LENGTH = 50
MAX_PASSWORD_LENGTH = 50
MAX_USER_EDIT_DIAGRAMS = 8
MAX_BAD_CONN_RETRIES = 5

#MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console': {
            'class': 'logging.StreamHandler',
        },
    },
    'loggers': {
        'django': {
            'handlers': ['console'],
             'level': os.getenv('DJANGO_LOG_LEVEL', 'DEBUG'),
        },
    },
}

# Activate Django-Heroku.
django_heroku.settings(locals())

The last part about LOGGING didn’t seem to do anything because I don’t see any extra logs or messages to the console anywhere on Heroku.

Have you tried testing locally with DEBUG = False?

3 Likes

@fabtjar I get the following error message, which is having to do with static files. However, I tried changing the

STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'

line to

STATICFILES_STORAGE = 'whitenoise.storage.CompressedStaticFilesStorage'

and it’s the same error, an error that gets thrown while reading a template of mine.

File "C:\Python39\Lib\site-packages\django\contrib\staticfiles\storage.py", line 147, in url
return self._url(self.stored_name, name, force)
File "C:\Python39\Lib\site-packages\django\contrib\staticfiles\storage.py", line 126, in _url
hashed_name = hashed_name_func(*args)
File "C:\Python39\Lib\site-packages\django\contrib\staticfiles\storage.py", line 417, in stored_name
raise ValueError("Missing staticfiles manifest entry for '%s'" % clean_name)

builtins.ValueError: Missing staticfiles manifest entry for 'bootstrap\css\bootstrap.min.css'

During handling of the above exception, another exception occurred:

File "C:\Python39\Lib\threading.py", line 930, in _bootstrap
self._bootstrap_inner()
File "C:\Python39\Lib\threading.py", line 973, in _bootstrap_inner
self.run()
File "C:\Python39\Lib\threading.py", line 910, in run
self._target(*self._args, **self._kwargs)
File "C:\Python39\Lib\socketserver.py", line 683, in process_request_thread
self.finish_request(request, client_address)
File "C:\Python39\Lib\socketserver.py", line 360, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "C:\Python39\Lib\socketserver.py", line 747, in __init__
self.handle()
File "C:\Python39\Lib\wsgiref\handlers.py", line 137, in run
self.result = application(self.environ, self.start_response)
File "C:\Python39\Lib\site-packages\whitenoise\middleware.py", line 59, in __call__
response = self.get_response(request)
File "C:\Python39\Lib\site-packages\whitenoise\middleware.py", line 59, in __call__
response = self.get_response(request)
![](C:\Program Files (x86)\Wing Pro 7.2/resources/icons/bookmarks_excpanel.png) File "C:\Users\FruitfulApproach\Desktop\abstract_spacecraft\database-of-proofs-engine\accounts\views.py", line 19, in sign_up
return render(request, 'sign_up.html', {'form': form})
![](C:\Program Files (x86)\Wing Pro 7.2/resources/icons/bookmarks_excpanel.png) File "c:\users\fruitfulapproach\desktop\abstract_spacecraft\database-of-proofs-engine\templates\accounts\sign_up.html", line (257, 303), in <django.templatetags.static.StaticNode object at 0x0000011CBF8CF370>
b'{% static "bootstrap\\css\\bootstrap.min.css" %}'

builtins.StopIteration

I also tried the solution here:

SO answer

and 3 other answers on StackOverflow, but same issues - either Server 500 (on heroku) or the above error (local).

I did run python manage.py collectstatic before running locally, and deploying to Heroku does this for you.

Does it error when you collect static locally? Can you show the sign up html page where you use the static CSS file?

1 Like

@fabtjar yes, still errors when collecting static locally. I get:

Not Found

The requested resource was not found on this server.
When I direct browser to domain/sign-in

The full code is here:
Github Repo

I mean the source for the html page. Are you sure the path to the CSS is correct?

1 Like

@fabtjar if it’s correct in development mode, it ought to be correct in production mode! :slight_smile:

I was asking because the error message shows ‘bootstrap\\css\\bootstrap.min.css’. I was just thinking are you using backslash because when you’re on Windows? I’m guessing Heroku’s server would be Linux.

1 Like

@fabtjar this error is taken from local though (Windows). I’ll try editing the template…

Thank you for solving this! Windows (local) running likes this as well, probably something to do with whatever server Django uses for serving files, i.e. that it needs forward slashes. Will have to update my BootstrapStudio export script (how I made the Bootstrap5 templates).

1 Like

I have the same problem. Also on cPanel deploy. This comment helped med get closer to the answer. Stil investigating.

In case you’re wondering why static files and images don’t work when Debug = False:

https://docs.djangoproject.com/en/4.1/howto/deployment/wsgi/modwsgi/#serving-files

I made images/static files be served by NGINX by configuring the config file like so:

nginx/default.conf

location: project root directory/nginx

upstream django {
    server django_gunicorn:8000; #I want the nginx server to proxy for this server and port
}

server {

listen 80; #proxy listens on port 80
client_max_body_size 30M; # max upload file size

   location / { #if it's not a static file, the request gets passed back to port 8000

       proxy_pass http://django; #"django" is inferred from what the upstream name was defined as
   }

   location /home/APROOT/app/jb_quality_prj/static/ {
       alias /static; # make nginx serve the static files
   }

   location /home/APPROOT/app/jb_quality_prj/media/ {
       alias /media; # make nginx serve the media files
   }
}

nginx/Dockerfile
location: project root directory/nginx

FROM nginx:1.19.0-alpine

COPY ./default.conf /etc/nginx/conf.d/default.conf

1 Like