{"record":{"id":"78744f0a050bd7f2","repo":"instructure/canvas-lms","slug":"folder-folder-does-not-exist","errorCode":null,"errorMessage":"Folder #{folder} does not exist.","messagePattern":"Folder #(.+?) does not exist\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gems/incoming_mail_processor/lib/incoming_mail_processor/directory_mailbox.rb","lineNumber":40,"sourceCode":"require \"zlib\"\n\nrequire_relative \"configurable_timeout\"\n\nmodule IncomingMailProcessor\n  class DirectoryMailbox\n    include ConfigurableTimeout\n\n    attr_accessor :folder\n\n    def initialize(options = {})\n      @folder = options.fetch(:folder, \"\")\n      @options = options\n      wrap_with_timeout(self,\n                        %i[folder_exists? files_in_folder read_file file? delete_file move_file create_folder])\n    end\n\n    def connect\n      raise \"Folder #{folder} does not exist.\" unless folder_exists?(folder)\n    end\n\n    def disconnect\n      # nothing to do\n    end\n\n    def each_message(opts = {})\n      filenames = files_in_folder(folder)\n      filenames = filenames.select { |filename| Zlib.crc32(filename) % opts[:stride] == opts[:offset] } if opts[:stride] && opts[:offset]\n      filenames.each do |filename|\n        if file?(folder, filename)\n          body = read_file(folder, filename)\n          yield filename, body\n        end\n      end\n    end\n\n    def delete_message(filename)","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/gems/incoming_mail_processor/lib/incoming_mail_processor/directory_mailbox.rb#L22-L58","documentation":"DirectoryMailbox#connect validates the configured incoming-mail directory before processing. If folder_exists?(folder) is false — the path configured as the mailbox does not exist on disk — connect raises immediately so the mail poller fails fast instead of silently processing nothing.","triggerScenarios":"Starting IncomingMessageProcessor with a directory mailbox whose :folder option points to a non-existent path; directory removed/renamed after config was written; wrong mount point or volume not mounted when running in a container.","commonSituations":"Typo or wrong absolute path in incoming mail settings; Docker/Kubernetes volume not mounted; permissions or deploy changed wiping the mail spool directory; staging config pointing at a host path that doesn't exist in the new environment.","solutions":["Create the configured folder: mkdir -p <configured folder path>.","Verify the :folder option in the incoming mail / canvas.yml settings matches an existing absolute path.","In containerized deployments, confirm the mail spool volume is mounted at the configured path.","Fix environment-specific config (staging vs production) so the directory exists where the process runs."],"exampleFix":"// before (config)\nincoming_mail:\n  mailbox: directory\n  folder: /var/mail/canvas_inbound   # does not exist\n// after\n# on host/container: mkdir -p /var/mail/canvas_inbound\nincoming_mail:\n  mailbox: directory\n  folder: /var/mail/canvas_inbound   # exists and writable by app user","handlingStrategy":"validation","validationCode":"folder = config[:folder]\nraise \"mailbox folder missing: #{folder}\" unless File.directory?(folder)","typeGuard":null,"tryCatchPattern":"begin\n  mailbox.connect\nrescue RuntimeError => e\n  raise unless e.message =~ /Folder .* does not exist/\n  FileUtils.mkdir_p(config[:folder])\n  retry\nend","preventionTips":["Provision the mail spool directory in deployment manifests (Dockerfile/entrypoint).","Use absolute paths and verify mounts in containerized environments.","Add a startup health check that fails early if the configured folder is absent."],"tags":["mail","filesystem","configuration","directory"],"backgroundTag":"directory-not-found","analyzedSha":"1c9f0bb8013ed69c4f2efe11fd483025469b7e6c","analyzedAt":"2026-09-15T20:33:18.891Z","contentChangedAt":"2026-09-15T20:33:18.891Z","schemaVersion":2},"datasetVersion":"2026-09-23T02:17:17.105Z"}