we-promise/sure · error · Provenance::Citation::InvalidError
estimated values must start with the exact prefix #{ESTIMATE
Error message
estimated values must start with the exact prefix #{ESTIMATED_PREFIX.inspect} What it means
Provenance::Citation.parse! raises InvalidError when the string matches the ESTIMATED_MARKER (starts with 'estimated' followed by optional whitespace and a colon, case-insensitive) but does not start with the exact prefix 'estimated: ' (lowercase, single space). This stops variants like 'Estimated:', 'estimated :', or 'ESTIMATED:' so an estimate can never lose its canonical marker on the way in.
Source
Thrown at app/models/provenance/citation.rb:47
# citation text and passing as an ungraded — but plausible-looking — source.
GRADE_SUFFIX = /\(grade:\s*(?<grade>[^)]*)\)\s*\z/
ESTIMATED_MARKER = /\Aestimated\s*:/i
class InvalidError < StandardError; end
attr_reader :raw, :text, :grade
class << self
# Returns a Citation, or raises InvalidError with a message written for the
# caller that has to fix it (an agent, usually).
def parse!(raw)
value = raw.to_s.strip
raise InvalidError, "source citation is required" if value.blank?
raise InvalidError, "source citation must be #{MAX_LENGTH} characters or fewer" if value.length > MAX_LENGTH
if value.match?(ESTIMATED_MARKER) && !value.start_with?(ESTIMATED_PREFIX)
raise InvalidError, "estimated values must start with the exact prefix #{ESTIMATED_PREFIX.inspect}"
end
if (suffix = value.match(GRADE_SUFFIX)) && !GRADES.include?(suffix[:grade])
raise InvalidError, "reliability grade must be one of #{GRADES.join(", ")} (got #{suffix[:grade].inspect})"
end
match = value.match(FORMAT)
raise InvalidError, "source citation does not match #{grammar}" unless match
text = match[:text].to_s.strip
if text.length < MIN_TEXT_LENGTH
raise InvalidError, "source citation must name the document it came from"
end
estimated = match[:estimated].present?
grade = match[:grade]
if estimated && grade.blank?View on GitHub (pinned to e69894adb9)
Solutions
- Use the exact prefix: start the citation with 'estimated: ' (lowercase, one space) — e.g. 'estimated: linear interpolation over anchors (grade: C)'.
- Normalize before parsing: strip, downcase just the marker, or value.sub(/\Aestimated\s*:/i, 'estimated: ').
- Include the grade suffix, since estimates also require a grade.
- Test with Provenance::Citation.valid? first and show the grammar in the error UI.
Example fix
# before
Provenance::Citation.parse!("Estimated: interpolated from 2024 anchors (grade: C)")
# after
normalized = raw.to_s.strip.sub(/\Aestimated\s*:/i, "estimated: ")
Provenance::Citation.parse!(normalized) Defensive patterns
Strategy: validation
Validate before calling
v = value.to_s
!v.match?(/\Aestimated\s*:/i) || v.start_with?("estimated: ") Type guard
def estimated_prefix_ok?(v) v = v.to_s.strip !v.match?(Provenance::Citation::ESTIMATED_MARKER) || v.start_with?(Provenance::Citation::ESTIMATED_PREFIX) end
Try / catch
begin Provenance::Citation.parse!(source) rescue Provenance::Citation::InvalidError => e source = source.sub(/\Aestimated\s*:/i, "estimated: ") # normalize and retry once retry end
Prevention
- Show the exact 'estimated: ' prefix in UI placeholder and agent prompts.
- Normalize case/spacing of the marker before parse rather than rejecting the user.
When it happens
Trigger: Citation beginning 'Estimated: ...', 'estimated : ...', 'ESTIMATED: ...', or 'estimated:\t...'; agent writing the marker with different casing or spacing.
Common situations: LLM capitalizing the prefix; human typing 'Estimated:'; a template that trims or reformats the leading prefix.
Related errors
- source citation is required
- source citation must be #{MAX_LENGTH} characters or fewer
- reliability grade must be one of #{GRADES.join(", ")} (got #
- source citation does not match #{grammar}
- source citation must name the document it came from
AI-assisted analysis of we-promise/sure@e69894adb9 (2026-08-21).
Data as JSON: /api/errors/821f8dafbe1ca069.
Report an issue: GitHub.