instructure/canvas-lms · error · Common::InvalidResultError

Unable to determine filename from Content-Disposition header

Error message

Unable to determine filename from Content-Disposition header

What it means

PageViews::FetchBatchResultService#determine_filename raises Common::InvalidResultError when the Content-Disposition header is missing or contains no filename matching /filename="?([^";]+)"?/. The service names the downloaded batch file from this header, so it refuses to guess.

Solutions

  1. Inspect response.header['Content-Disposition'] to see what the server sends
  2. Fall back to a locally generated filename when the header is absent (wrap determine_filename path in a rescue)
  3. Check upstream/proxy settings that drop or rewrite Content-Disposition
  4. Confirm you are fetching the result download URL, not the status URL

Example fix

// before
filename = service.call(response) # raises when header missing
// after
filename = service.call(response)
rescue PageViews::Common::InvalidResultError => e
  raise unless e.message.include?('filename')
  filename = "page_views_batch_#{Time.now.to_i}.csv"
Defensive patterns

Strategy: fallback

Validate before calling

cd = response.header['Content-Disposition'].to_s
has_filename = cd.match?(/filename="?([^";]+)"?/)

Try / catch

begin
  filename = service.call(response)
rescue PageViews::Common::InvalidResultError => e
  raise unless e.message.include?('filename')
  filename = "page_views_#{Time.now.strftime('%Y%m%d%H%M%S')}.csv"
end

Prevention

When it happens

Trigger: Response has no Content-Disposition header, or it lacks a filename parameter (e.g. 'attachment' alone, or an inline disposition).

Common situations: Proxy stripping Content-Disposition; API version change altering header formatting; error responses that skip attachment headers; CDN configurations that rewrite dispositions.

Related errors


AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15). Data as JSON: /api/errors/34df6bf44b27da3d. Report an issue: GitHub.

Appendix: source

Thrown at app/services/page_views/fetch_batch_result_service.rb:53

    private

    def determine_result_format(response)
      raise InvalidResultError, "Missing Content-Type header in response." unless response.header["Content-Type"]

      # strip any parameters (encoding for example) from the Content-Type
      content_type = response.header["Content-Type"].split(";").first.strip
      raise Common::InvalidResultError, "Result format is invalid: #{content_type}" unless Common::CONTENT_TYPE_MAPPINGS[content_type]

      Common::CONTENT_TYPE_MAPPINGS[content_type]
    end

    def determine_filename(response)
      content_disposition = response.header["Content-Disposition"]
      if content_disposition && content_disposition =~ /filename="?([^";]+)"?/
        Regexp.last_match(1)
      else
        raise Common::InvalidResultError, "Unable to determine filename from Content-Disposition header"
      end
    end
  end
end

View on GitHub (pinned to 1c9f0bb801)