instructure/canvas-lms · critical

you must run "gulp rev" first

Error message

you must run "gulp rev" first

What it means

The gulp CDN registry maps original asset paths to fingerprinted ones via public/dist/rev-manifest.json, generated by 'gulp rev'. In production, if that manifest is missing, it raises this error instead of silently returning an empty map (as it does in dev). Serving assets without it would produce wrong/unfingerprinted URLs.

Solutions

  1. Run yarn/gulp build including 'gulp rev' to generate public/dist/rev-manifest.json
  2. Rebuild the production asset bundle as part of the deploy pipeline
  3. Ensure RAILS_ENV is not production for local dev, or commit/generate manifests before boot
  4. Verify file existence in the deploy health check before starting Rails

Example fix

// before
Rails.env.production? && !Rails.public_path.join('dist/rev-manifest.json').exist? # raises
// after
$ gulp rev   # writes public/dist/rev-manifest.json
Defensive patterns

Strategy: fallback

Validate before calling

raise 'rev manifest missing' unless Rails.public_path.join('dist/rev-manifest.json').exist?

Try / catch

begin
  registry.load_manifest_from_disk
rescue RuntimeError => e
  raise unless e.message.include?('gulp rev')
  {}
end

Prevention

When it happens

Trigger: Any asset-path lookup through the gulp registry in a production Rails env where public/dist/rev-manifest.json does not exist at boot of load_manifest_from_disk.

Common situations: Production image built without running gulp rev; manifest wiped by a public/ cleanup; running rails in RAILS_ENV=production on a laptop without the full frontend build.

Related errors


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

Appendix: source

Thrown at lib/canvas/cdn/registry/gulp.rb:54

        def url_for(file)
          #   source looks like "/images/apple-touch-icon.png"
          #             or like "/dist/images/apple-touch-icon.png"
          # virtpath looks like "images/apple-touch-icon.png"
          # realpath looks like "/dist/images/apple-touch-icon-585e5d997d.png"
          if (fingerprinted = @manifest[virtpath(file)])
            realpath(fingerprinted)
          end
        end

        private

        def load_manifest_from_disk
          file = Rails.public_path.join("dist/rev-manifest.json")

          if file.exist?
            JSON.parse(file.read).freeze
          elsif Rails.env.production?
            raise "you must run \"gulp rev\" first"
          else
            {}
          end
        end

        def virtpath(source)
          normal = source.sub(%r{^/}, "")

          if normal.start_with?(@asset_dir)
            normal[(@asset_dir.length + 1)..]
          else
            normal
          end
        end

        def realpath(vfile)
          "/#{@asset_dir}/#{vfile}"
        end

View on GitHub (pinned to 1c9f0bb801)