{"record":{"id":"a33b41496e7a130c","repo":"docusealco/docuseal","slug":"invalid-submitter-params","errorCode":null,"errorMessage":"Invalid submitter params","messagePattern":"Invalid submitter params","errorType":"validation","errorClass":"Submissions::CreateFromSubmitters::BaseError","httpStatus":422,"severity":"error","filePath":"lib/submissions/create_from_submitters.rb","lineNumber":59,"sourceCode":"\n            uuid = template_submitter['uuid']\n          else\n            if submitter_attrs[:roles].present? && submitter_attrs[:roles].size == 1\n              submitter_attrs[:role] = submitter_attrs[:roles].first\n            end\n\n            uuid = find_submitter_uuid(template_submitters, submitter_attrs, index)\n\n            next if uuid.blank?\n            next if submitter_attrs.slice('email', 'phone', 'name').compact_blank.blank?\n\n            submission.template_fields = submission.template.fields if submitter_attrs[:completed].present? &&\n                                                                       submission.template_fields.blank?\n\n            template_submitter = template_submitters.find { |e| e['uuid'] == uuid }\n          end\n\n          raise BaseError, 'Invalid submitter params' unless template_submitter\n\n          template_submitter = template_submitter.except('optional_invite_by_uuid', 'invite_by_uuid',\n                                                         'invite_via_field_uuid')\n\n          template_submitter['order'] = submitter_attrs['order'] if submitter_attrs['order'].present?\n\n          submission.template_submitters << template_submitter\n\n          is_order_sent = submitters_order == 'random' ||\n                          (template_submitter['order'] || submitter_attrs[:index] || index).zero?\n\n          build_submitter(submission:, attrs: submitter_attrs,\n                          uuid:, is_order_sent:, user:, params:,\n                          preferences: preferences.merge(submission_preferences))\n        end\n\n        maybe_set_dynamic_documents(submission)\n        maybe_set_template_fields(submission, attrs[:submitters], with_template:, new_fields:)","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/docusealco/docuseal/blob/004a22c1c88109c7ba0b567df011a8cb13894001/lib/submissions/create_from_submitters.rb#L41-L77","documentation":"Submissions::CreateFromSubmitters raises BaseError 'Invalid submitter params' (lib/submissions/create_from_submitters.rb:59) when a submitter entry cannot be matched to any party defined by the template. The uuid is resolved by find_submitter_uuid from (in priority) attrs[:uuid], a case-insensitive role name match on attrs[:role], or positional index; if that resolved uuid does not exist in template_submitters, template_submitter stays nil and the error fires.","triggerScenarios":"POST /api/submissions with a submitters entry whose role/uuid matches none of template.submitters (typo'd role name like 'Signer ' vs 'Signer'); an entry with no uuid/role falling back to an index beyond the template's party count; a uuid copied from a different template; the merge path (attrs[:roles]) raising earlier but leaving a nil template_submitter from a previous skipped iteration.","commonSituations":"Template roles renamed after an integration was coded; templates recreated and old cached uuids reused; clients sending more subitters than roles expecting extras to be ignored; API consumers assuming 1-based or uuid-based ordering that does not match find_submitter_uuid's index fallback.","solutions":["Fetch the template's parties first (template.submitters names/uuids) and send only role (case-insensitive exact), uuid, or in-range index values that match them.","If you need one signer to cover several roles, send roles: ['First Role', 'Second Role'] on a single entry instead of duplicating entries with made-up roles.","Remove surplus submitter entries — every entry must map to a template party (entries without email/phone/name are skipped by design at line 51).","Regenerate any hard-coded uuids after a template is duplicated or edited."],"exampleFix":"# before\nSubmissions::CreateFromSubmitters.call(\n  template:, user:, source: 'api', submitters_order: 'preserved',\n  submissions_attrs: [{ submitters: [{ role: 'Singger', email: 'a@b.c' }] }] # typo\n)\n\n# after\nSubmissions::CreateFromSubmitters.call(\n  template:, user:, source: 'api', submitters_order: 'preserved',\n  submissions_attrs: [{ submitters: [{ role: template.submitters.first['name'], email: 'a@b.c' }] }]\n)","handlingStrategy":"validation","validationCode":"# Validate submitters attrs against the template before calling CreateFromSubmitters\ndef valid_submitter_params?(template, submitters_attrs)\n  known_uuids = template.submitters.map { |s| s['uuid'] }\n  known_roles = template.submitters.map { |s| s['name'].downcase }\n\n  Array(submitters_attrs).all? do |attrs_entry|\n    Array(attrs_entry[:submitters]).all? do |s|\n      next true if s[:uuid].present? && s[:uuid].in?(known_uuids)\n      next true if s[:role].present? && known_roles.include?(s[:role].to_s.downcase)\n      next true if s[:uuid].blank? && s[:role].blank? && # index fallback in range\n                   (s[:index] || submitters_attrs.index(attrs_entry)).to_i < known_uuids.size\n\n      false\n    end\n  end\nend","typeGuard":null,"tryCatchPattern":"begin\n  Submissions::CreateFromSubmitters.call(template:, user:, submissions_attrs:, source:, submitters_order:)\nrescue Submissions::CreateFromSubmitters::BaseError => e\n  render json: { error: e.message }, status: :unprocessable_entity\nend","preventionTips":["Always fetch roles/uuids from the live template instead of hard-coding them.","Regenerate stored uuids whenever a template is duplicated or its parties edited.","Role matching is case-insensitive but exact otherwise — trim stray whitespace.","Entries lacking email/phone/name are silently skipped; do not rely on that to fix bad roles."],"tags":["docuseal","submissions","params-validation","template-roles"],"backgroundTag":"invalid-request-params","analyzedSha":"004a22c1c88109c7ba0b567df011a8cb13894001","analyzedAt":"2026-08-21T13:38:23.343Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}