docusealco/docuseal · error · Params::BaseValidator::InvalidParameterError
#{message}
Error message
#{message} What it means
Params::BaseValidator is the base class for structured API parameter validation; raise_error appends the current JSON path ('in `path`') and raises InvalidParameterError unless the validator runs in dry_run mode. The literal message is interpolated - each concrete validator supplies texts like 'x or y is required' from the required/type helpers. These errors back the API's invalid-parameter (422-style) responses.
Source
Thrown at lib/params/base_validator.rb:40
attr_reader :params, :dry_run
alias dry_run? dry_run
def initialize(params, dry_run: false)
@params = params
@dry_run = dry_run
@current_path = ''
end
def call
raise NotImplementedError
end
def raise_error(message)
message += " in `#{@current_path}`." if @current_path.present?
raise InvalidParameterError, message unless dry_run?
end
def required(params, keys, message: nil)
keys = Array.wrap(keys)
return if keys.any? { |key| params&.dig(key).present? }
raise_error(message || "#{keys.join(' or ')} is required")
end
def type(params, key, type, message: nil)
return if params.blank?
return if params[key].blank?
return if params[key].is_a?(type) || (type == Hash && params[key].is_a?(ActionController::Parameters))
type = 'Object' if type == Hash
View on GitHub (pinned to 004a22c1c8)
Solutions
- Read the message literally: it names the exact parameter and the JSON path where validation failed.
- Diff your payload against the endpoint's documented schema and fix nesting per the path suffix.
- Use the validator's dry_run mode in tests to collect all errors at once instead of one per request.
- If the message seems wrong, check the endpoint's validator class for the exact required/type rules.
Example fix
# before required(params, %i[template_id]) # after -- clearer message for API consumers required(params, %i[template_id], message: 'template_id or template_blob is required')
Defensive patterns
Strategy: validation
Validate before calling
// client-side: check required keys before sending
const REQUIRED = ['template_id']
const missing = REQUIRED.filter((k) => body[k] == null)
if (missing.length) throw new Error(`Missing: ${missing.join(', ')}`) Type guard
const hasRequiredKeys = (b) => typeof b === 'object' && b !== null && REQUIRED.every((k) => b[k] != null && b[k] !== '')
Try / catch
try {
await api.post('/api/submissions', body)
} catch (e) {
if (e.status === 422) mapFieldErrors(e.body) // message names the param + path
else throw e
} Prevention
- Generate typed clients from the API schema
- Use dry-run validators in integration tests
- Log the full rejected payload (sans secrets) on 422
When it happens
Trigger: Calling a validated API endpoint with missing required keys, wrong types, or values failing nested checks - for example a create call missing every key passed to required(), or a string sent where the type check expects an array.
Common situations: API consumers omitting optional-looking-but-required fields; wrong request nesting (the path suffix in the message shows where); schema changes between versions; integrations written against outdated docs.
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 docusealco/docuseal@004a22c1c8 (2026-08-21).
Data as JSON: /api/errors/6dbb0895b9be2086.
Report an issue: GitHub.