docusealco/docuseal · error · Submitters::SubmitValues::ValidationError

Read-only field

Error message

Read-only field

What it means

Raised by Submitters::SubmitValues.validate_value! when the values hash writes to a field whose readonly attribute is exactly true. Readonly fields (e.g. the auto-created decline-reason text field, prefilled/computed fields) are display-only; the attempted write is also logged to Rollbar as 'Readonly field' when Rollbar is defined.

Source

Thrown at lib/submitters/submit_values.rb:507

        SubmissionEvents.create_with_tracking_data(submitter, 'invite_party', request, { uuid: submitter.uuid })

        is_invited = true
      end

      submission.update!(submitters_order: :preserved) if is_invited

      submitter
    end

    def validate_value!(_value, field, _params, submitter, _request)
      raise ValidationError, 'Missing field' unless field
      raise ValidationError, 'Invalid field' if field['submitter_uuid'] != submitter.uuid

      if field['readonly'] == true
        Rollbar.warning("Readonly field #{submitter.id}: #{field['uuid']}") if defined?(Rollbar)

        raise ValidationError, 'Read-only field'
      end

      true
    end
  end
end

View on GitHub (pinned to 004a22c1c8)

Solutions

  1. Remove readonly fields from the values payload (slice to writable fields before submitting)
  2. If the field must be editable, set readonly to false in the template field definition
  3. Never write values for internally created fields such as decline-reason fields — they are readonly by design

Example fix

# before
values = values.merge('readonly_field_uuid' => 'new value') # raises 'Read-only field'
# after
writable = submitter.submission.template_fields.reject { |f| f['readonly'] == true }
values = values.slice(*writable.map { |f| f['uuid'] })
Defensive patterns

Strategy: validation

Validate before calling

writable_uuids = submitter.submission.template_fields
                            .reject { |f| f['readonly'] == true }
                            .map { |f| f['uuid'] }
values = values.slice(*writable_uuids)

Type guard

def writable_field?(uuid, submission)
  field = submission.fields_uuid_index[uuid]
  !field.nil? && field['readonly'] != true
end

Try / catch

begin
  Submitters::SubmitValues.call(submitter, params, request)
rescue Submitters::SubmitValues::ValidationError => e
  # e.message == 'Read-only field' -> client tried to write a locked field
  render json: { error: e.message }, status: :unprocessable_entity
end

Prevention

When it happens

Trigger: Submitting a value for a field configured readonly: true in the template — commonly the auto-created 'Reason' field (created with 'readonly' => true) or any field an admin locked after prefilling defaults.

Common situations: An integration prefills readonly defaults and then posts the whole values object back; the auto-created reason field from a previous decline keeps being included in later submits; a UI bug leaves an input enabled for a locked field; template switched a field to readonly but the client still sends it.

Related errors


AI-assisted analysis of docusealco/docuseal@004a22c1c8 (2026-08-21). Data as JSON: /api/errors/f8364cb88e524462. Report an issue: GitHub.