docusealco/docuseal · error · Submitters::ParamsError
file param is missing
Error message
file param is missing
What it means
Submitters.create_attachment! (lib/submitters.rb:127) raises ParamsError 'file param is missing' when the uploaded file argument is blank before it ever touches storage. It is the guard for submitter attachment upload endpoints (e.g. adding documents/images to a submitter): the multipart 'file' field must be present and non-empty.
Source
Thrown at lib/submitters.rb:127
if AccountConfig.exists?(account_id: submitter.account_id,
key: AccountConfig::COMBINE_PDF_RESULT_KEY,
value: true) &&
submitter.submission.completed_at? &&
submitter.submission.template_fields.none? { |f| f['type'] == 'verification' }
return [submitter.submission.combined_document_attachment || Submissions::EnsureCombinedGenerated.call(submitter)]
end
original_documents = submitter.submission.schema_documents.preload(:blob)
is_more_than_two_images = original_documents.many?(&:image?)
submitter.documents.preload(:blob).reject do |attachment|
is_more_than_two_images &&
original_documents.find { |a| a.uuid == (attachment.metadata['original_uuid'] || attachment.uuid) }&.image?
end
end
def create_attachment!(submitter, file, metadata: {})
raise ParamsError, 'file param is missing' if file.blank?
extension = File.extname(file.original_filename).delete_prefix('.').downcase
if DANGEROUS_EXTENSIONS.include?(extension)
raise MaliciousFileExtension, "File type '.#{extension}' is not allowed."
end
blob = ActiveStorage::Blob.create_and_upload!(io: file.tap(&:rewind).open,
filename: file.original_filename,
content_type: file.content_type,
metadata:)
ActiveStorage::Attachment.create!(blob:, name: 'attachments', record: submitter)
end
def normalize_preferences(account, user, params)
preferences = {}
View on GitHub (pinned to 004a22c1c8)
Solutions
- Send the request as multipart/form-data with the exact file field name the endpoint expects (Rack yields an ActionDispatch::Http::UploadedFile).
- Client-side, assert a file is selected before submitting and disable the upload button otherwise.
- If using curl: curl -F 'file=@doc.pdf' (not -d).
- Rescue Submitters::ParamsError at the controller boundary and map it to a 400 with this message.
Example fix
# before (JSON body — file param never materializes)
fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({}) })
# after
const form = new FormData()
form.append('file', fileInput.files[0])
fetch(url, { method: 'POST', body: form }) Defensive patterns
Strategy: validation
Validate before calling
# Validate the upload before calling create_attachment!
def upload_file?(param)
param.is_a?(ActionDispatch::Http::UploadedFile) && param.present? &&
param.original_filename.present?
end Try / catch
begin
Submitters.create_attachment!(submitter, params[:file])
rescue Submitters::ParamsError => e
render json: { error: e.message }, status: :bad_request
end Prevention
- Send multipart/form-data (FormData / curl -F), never a JSON body, for file uploads.
- Use the exact file field name the endpoint documents.
- Disable submit until a file is chosen client-side.
- Map ParamsError to 400 at the controller boundary.
When it happens
Trigger: POST to the submitter attachments endpoint as JSON instead of multipart/form-data so params[:file] is a string/absent; multipart body missing the file field or using a different field name; an empty file part (0-byte with blank Rack object); calling create_attachment! internally with nil.
Common situations: Frontends sending fetch with Content-Type: application/json instead of FormData; curl posts without -F; reverse proxies or body-size limits stripping large parts; field named 'document' or 'files' instead of the expected param.
Related errors
- Invalid submitter params
- Defined more signing parties than in template
- Recipient emails should differ
- File type '.#{extension}' is not allowed.
- Invalid #{type} value
AI-assisted analysis of docusealco/docuseal@004a22c1c8 (2026-08-21).
Data as JSON: /api/errors/984410e130fde9a3.
Report an issue: GitHub.