Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

[BUG] (ofrep) Error responses are parsed with snake_case keys, so no spec-conformant 400 can be parsed

Open Beginner friendly
#283 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
85/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
ruby
Domain
api

Research direction

Start at lib/openfeature/ofrep/provider/client.rb in parse_error_response (around lines 101-119): change the required keys and parsed reads to camelCase (errorCode, errorDetails). Then update the stubbed error bodies in spec/openfeature/ofrep/provider/client_spec.rb and provider_spec.rb so the suite exercises the spec casing. Run those specs; done means a spec-conformant 400 returns the default value with the server's error code and message instead of raising ParseError, with any optional Provider#evaluate rescue work kept in scope only if agreed.

Written by the indexing model from the issue text.

Description

Description

OpenFeature::OFREP::Client#parse_error_response reads error response bodies using
snake_case keys (error_code, error_details), but OFREP specifies camelCase
(errorCode, errorDetails).

As a result the provider cannot parse a 400 from any spec-conformant OFREP server.
Because ParseError is not rescued by Provider#evaluate, and openfeature-sdk 0.3.1
(the pinned version) does not rescue provider exceptions either, the exception propagates
out of the application's flag-evaluation call.

Success parsing is unaffected and correct — this is only the error path.

The spec

evaluationFailure in service/openapi.yaml:

evaluationFailure:
  type: object
  properties:
    key:          { $ref: "#/components/schemas/key" }
    errorCode:    { type: string, enum: [PARSE_ERROR, TARGETING_KEY_MISSING, INVALID_CONTEXT, GENERAL] }
    errorDetails: { $ref: "#/components/schemas/errorDetails" }
  required: [key, errorCode]

bulkEvaluationFailure uses the same casing and requires errorCode.

The code

lib/openfeature/ofrep/provider/client.rb:101-119 (v0.1.2):

def parse_error_response(response)
  required_keys = %w[key error_code]          # spec: key, errorCode
  parsed = JSON.parse(response.body)

  missing_keys = required_keys - parsed.keys
  unless missing_keys.empty?
    raise OpenFeature::OFREP::ParseError.new(response)
  end

  OpenFeature::OFREP::Response.new(
    ...
    error_code: error_code_mapper(parsed["error_code"]),     # spec: errorCode
    error_details: parsed["error_details"],                  # spec: errorDetails
    ...
  )
end

For contrast, parse_success_response (line 121) is correct: %w[key value reason variant].

Steps to Reproduce

Point the provider at any spec-conformant OFREP server and trigger a 400 (for example by
sending a context the server rejects). The response body is the one from the spec's own
example, openapi.yaml lines 88-91:

{
  "key": "my-flag",
  "errorCode": "INVALID_CONTEXT",
  "errorDetails": "Context property 'plan' must be a string"
}

The defect is in version-independent code, so it can be shown with the two constants
copied verbatim from client.rb:

require "json"

ERROR_REQUIRED = %w[key error_code]   # client.rb:102

body = '{"key":"my-flag","errorCode":"INVALID_CONTEXT","errorDetails":"..."}'
ERROR_REQUIRED - JSON.parse(body).keys
# => ["error_code"]  -> raise OpenFeature::OFREP::ParseError

Expected Behavior

Per OpenFeature spec requirement 1.4.10, evaluation does not raise. The caller receives the
default value, the server's error code (INVALID_CONTEXT here) and its errorDetails
message:

#<ResolutionDetails value=<default> error_code="INVALID_CONTEXT"
                    error_message="Context property 'plan' must be a string"
                    reason="ERROR">

Actual Behavior

OpenFeature::OFREP::ParseError is raised and reaches the caller:

  1. parse_error_response raises ParseError — error_code is absent from the body.
  2. Provider#evaluate (provider.rb:84-87) rescues only UnauthorizedError,
    InvalidOptionError, FlagNotFoundError and InternalServerError. ParseError is
    not in that list.
  3. openfeature-sdk 0.3.1 Client#fetch_*_value has no rescue at all (its only rescue
    is in api.rb:51, around client construction).

So client.fetch_boolean_value(...) raises instead of returning the default. The server's
real error code and message are lost in every case.

Note that on a newer openfeature-sdk, fetch_details rescues RECOVERABLE_ERRORS and
this would instead degrade to a misleading PARSE_ERROR with error_message="Parse error"
— better, but still the wrong code and still discarding the server's errorDetails. The
casing needs fixing either way.

Environment

  • Ruby version: n/a — version-independent parsing logic (gem requires >= 3.4)
  • Provider/Hook: ofrep (openfeature-ofrep-provider)
  • Provider/Hook version: 0.1.2 (also present on main)
  • OS: n/a
  • openfeature-sdk version: 0.3.1 (the version the gemspec pins, ~> 0.3.1)

Additional Context

The existing tests encode the same casing, which is why this is green in CI. From
spec/openfeature/ofrep/provider/client_spec.rb, the stubbed server responses:

error_code: "TYPE_MISMATCH",
error_details: "expected type: boolean, got: string"

So a fix needs the fixtures corrected alongside the source, otherwise the suite fails for
the right reason and looks like a regression.

Suggested fix:

  • required_keys = %w[key errorCode], reading parsed["errorCode"] / parsed["errorDetails"].
  • Update the error-path fixtures in client_spec.rb and provider_spec.rb to camelCase.
  • Optionally add ParseError and RateLimited to the rescue list in Provider#evaluate,
    so a malformed body from a server still returns a default rather than raising. (Happy to
    split that into its own issue if you'd rather keep this one to the casing.)

I'm glad to open a PR for this.

Dominant language
Ruby
Stars
5
Forks
13
Avg merge
15m
Merged PRs (30d)
35

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from open-feature/ruby-sdk-contrib

All issues in open-feature/ruby-sdk-contrib

Similar issues

More Ruby issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.