Preventing an ActionController::Session::CookieStore::CookieOverflow Error

One of my clients is a heavy user of my Redmine Timesheet plugin and they reported some strange 500 errors to me today. After digging through their logs I saw the plugin was throwing an ActionController::Session::CookieStore::CookieOverflow error. This means that more than 4K of data is being stored into a cookie, which is invalid.

For those who don’t know, Redmine Timesheet tries to store your last report options into your session so it can remember what you last selected. So if you run a report for “today, all users” those values are saved as your defaults when you come back later. unfortunately for my client, their last report options had so much data that it was overflowing the cookie.

After doing a bit of digging I found out how to test how much data you are going to store into a cookie and let your code handle a workaround.

  def save_filters_to_session(timesheet)
    if params[:timesheet]
      # Check that the params will fit in the session before saving
      # prevents an ActionController::Session::CookieStore::CookieOverflow
      encoded = Base64.encode64(Marshal.dump(params[:timesheet]))
      if encoded.size < 2.kilobytes # Only use 2K of the cookie
        session[SessionKey] = params[:timesheet]

The main part is on lines 5 and 6 where I’m using Marshal.dump and Base64.encode64 to see what the actual data would look like. Once you have the encoded data you can check it’s size easily. I picked 2K because:

  • Rails itself uses a bit of the cookie space for encrypting the data and session secret
  • Redmine / ChiliProject stores the user_id in the cookie, which takes a few bytes
  • Redmine / ChiliProject stores a few other things in the cookie like the last Issue query you ran, which can add up to quite a bit of data too

On line 8 you can also see that I’m not doing anything if the data is too large for the cookie (else case). Since this feature is a convenience feature, it is the simplest thing to do. You could do something else if you have to store the data, like purge old cookie data or something…

I hope this helps someone who runs across the ActionController::Session::CookieStore::CookieOverflow error.

Example code in my Redmine Timesheet plugin with an integration test.