Status
Confirmed on 2026-09-13 against src/errors.ts on main (7fd722b), which includes #114.
- Executed: the regex itself.
- Read, not executed: the
code path in errorFromResponse.
- Live API body: captured the same day.
Defect
MACHINE_CODE = /^[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)+$/ (src/errors.ts:99) accepts only upper-snake codes. The API also sends lower-snake machine codes in the fail envelope, each with its own message:
invalid_code from app/controllers/concerns/api_validations.rb. The API comment there says clients parse error.
no_price_data and invalid_request from app/controllers/v1/prices_controller.rb.
$ node -e 'const MACHINE_CODE = /^[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)+$/; for (const s of ["invalid_code","no_price_data","invalid_request","VALIDATION_ERROR"]) console.log(s, MACHINE_CODE.test(s));'
invalid_code false
no_price_data false
invalid_request false
VALIDATION_ERROR true
So failCode is undefined for these bodies. code (src/errors.ts:166, stringValue(envelope.code) || stringValue(envelope.error_code) || failCode) is undefined, and the machine code is lost. message still comes from data.message, so only the code is dropped.
Live body, GET /v1/prices/latest?by_code=NOT_A_REAL_CODE_XYZ, HTTP 400:
{"status": "fail", "data": {"error": "invalid_code", "message": "Code 'NOT_A_REAL_CODE_XYZ' not found. No close match found. See /v1/commodities for all available codes.", "suggestions": [], "did_you_mean": [], "invalid_codes": ["NOT_A_REAL_CODE_XYZ"], "all_codes_url": "https://api.oilpriceapi.com/v1/commodities"}}
Expected
Treat a lower-snake token as a machine code too, while a sentence still stays the message. The Python SDK fix for the same defect (OilpriceAPI/python-sdk#145) accepts a snake-case token that is all upper or all lower: ASCII alphanumerics joined by _, starting with a letter. With that fix, invalid_code stays error.code.
Add a test with the live body above asserting code === "invalid_code" and message equal to the sentence.
Status
Confirmed on 2026-09-13 against
src/errors.tsonmain(7fd722b), which includes #114.codepath inerrorFromResponse.Defect
MACHINE_CODE = /^[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)+$/(src/errors.ts:99) accepts only upper-snake codes. The API also sends lower-snake machine codes in the fail envelope, each with its ownmessage:invalid_codefromapp/controllers/concerns/api_validations.rb. The API comment there says clients parseerror.no_price_dataandinvalid_requestfromapp/controllers/v1/prices_controller.rb.So
failCodeisundefinedfor these bodies.code(src/errors.ts:166,stringValue(envelope.code) || stringValue(envelope.error_code) || failCode) isundefined, and the machine code is lost.messagestill comes fromdata.message, so only the code is dropped.Live body,
GET /v1/prices/latest?by_code=NOT_A_REAL_CODE_XYZ, HTTP 400:{"status": "fail", "data": {"error": "invalid_code", "message": "Code 'NOT_A_REAL_CODE_XYZ' not found. No close match found. See /v1/commodities for all available codes.", "suggestions": [], "did_you_mean": [], "invalid_codes": ["NOT_A_REAL_CODE_XYZ"], "all_codes_url": "https://api.oilpriceapi.com/v1/commodities"}}Expected
Treat a lower-snake token as a machine code too, while a sentence still stays the message. The Python SDK fix for the same defect (OilpriceAPI/python-sdk#145) accepts a snake-case token that is all upper or all lower: ASCII alphanumerics joined by
_, starting with a letter. With that fix,invalid_codestayserror.code.Add a test with the live body above asserting
code === "invalid_code"andmessageequal to the sentence.