instructure/canvas-lms · error · SubmissionError

Invalid file type

Error message

Invalid file type

What it means

CreateSubmissionDraft#verify_allowed_extensions! enforces the assignment's allowed_extensions list for online_upload submissions. If the assignment restricts extensions and any attachment's extension is not in the list (case-insensitive), it raises SubmissionError "Invalid file type".

Solutions

  1. Convert/rename the file so its extension matches one in the assignment's allowed_extensions.
  2. Check the assignment's allowedExtensions via GraphQL and validate client-side before upload.
  3. Ask the instructor to update allowed_extensions if the file type should be permitted.
  4. Ensure the uploaded Attachment actually retains its extension (after_extension not empty).

Example fix

// before
fileIds: [idOf("report.exe")]
// after
fileIds: [idOf("report.pdf")] // extension now in allowedExtensions: ["pdf"]
Defensive patterns

Strategy: validation

Validate before calling

const allowed = (assignment.allowedExtensions || []).map(e => e.toLowerCase())
const bad = files.filter(f => !allowed.includes(f.name.split('.').pop().toLowerCase()))
if (assignment.allowedExtensions?.length && bad.length) throw new SkipError('invalid file type: ' + bad.map(f => f.name))

Type guard

function hasAllowedExtension(file, allowed) { return !allowed?.length || allowed.includes((file.name.split('.').pop() || '').toLowerCase()); }

Try / catch

try {
  await createSubmissionDraft({ fileIds })
} catch (e) {
  if (e.message === 'Invalid file type') {
    alertUserToConvertFile(assignment.allowedExtensions)
  } else throw e;
}

Prevention

When it happens

Trigger: Drafting a file upload submission where assignment.allowed_extensions is non-blank and an attachment's after_extension (downcased) is not included, e.g. uploading .exe when only .pdf,.docx allowed; attachment with no extension while restrictions exist.

Common situations: Instructor tightened allowed extensions after students already uploaded files; file renamed without actually converting format; macOS hidden extension issues; uploading files with uppercase extensions is fine but files with none are rejected.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at app/graphql/mutations/create_submission_draft.rb:162

  end

  def validate_file_ids!(file_id_attachments, valid_attachment_ids)
    file_ids = file_id_attachments.pluck(:id).map(&:to_s)
    file_ids.each do |file_id|
      next if valid_attachment_ids.include?(file_id)

      raise SubmissionError, I18n.t(
        "No attachments found for the following ids: %{ids}",
        { ids: file_ids - valid_attachment_ids }
      )
    end
  end

  # TODO: move this into the model
  def verify_allowed_extensions!(assignment, attachments)
    return if assignment.allowed_extensions.blank?

    raise SubmissionError, I18n.t("Invalid file type") unless attachments.all? do |attachment|
      attachment_extension = attachment.after_extension || ""
      assignment.allowed_extensions.include?(attachment_extension.downcase)
    end
  end

  def get_attachment_ids(file_ids)
    return [] if file_ids.empty?

    joined_file_ids = file_ids.to_a.join(",")
    sql = <<~SQL.squish
      SELECT
        p.a_id,
        p.ra_id
      FROM
        (
          (
            SELECT
              a.id as a_id,

View on GitHub (pinned to 1c9f0bb801)