Skip to content

get_golf_shot_data() always returns HTTP 400 "Invalid hole-numbers" (commas are URL-encoded) #377

Description

@antoine-defrahan

Environment

  • garminconnect 0.3.6 (latest on PyPI)
  • Python 3.12, macOS
  • Authenticated via saved tokens (Garmin().login(tokenstore))

Describe the bug

get_golf_shot_data() fails for every scorecard when there is a comma in the hole parameter. Any call raises:

garminconnect.exceptions.GarminConnectConnectionError: API call client error (400):
API Error 400 - {'errorMessage': 'Invalid hole-numbers in request'}

To reproduce

from garminconnect import Garmin

api = Garmin()
api.login("~/.garminconnect")

# grab any scorecard id
sid = api.get_golf_summary(start=0, limit=1)["scorecardSummaries"][0]["id"]

api.get_golf_shot_data(sid)   # -> GarminConnectConnectionError: 400 Invalid hole-numbers

Root cause

get_golf_shot_data() builds the request with a comma-separated default:

def get_golf_shot_data(
    self,
    scorecard_id: int | str,
    hole_numbers: str = "1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18",
) -> dict[str, Any]:
    ...
    url = f"{self.garmin_golf_shot}/{scorecard_id}/hole"
    params = {"hole-numbers": hole_numbers}
    return self.connectapi(url, params=params)

requests percent-encodes the commas in the query string (,%2C), and the Garmin
endpoint rejects the encoded form. Any value containing a comma fails.

I confirmed this by varying only the parameter against the same scorecard:

params Result
{"hole-numbers": "1,2,...,18"} (the default) ❌ 400 Invalid hole-numbers
{"hole-numbers": "1, 2, 3"} ❌ 400 Invalid hole-numbers
{"hole-numbers": "1"} (no comma) ✅ returns 1 hole
{"hole-numbers": "1-18"} (no comma) ✅ returns 2 holes (parsed as 1 and 18)
no hole-numbers param at all ✅ returns all 18 holes

Suggested fix

  1. Omit hole-numbers when the caller doesn't specify holes. The endpoint already
    returns every hole when the parameter is absent, which is what the current default is
    trying to express anyway.
  2. Send the parameter without encoding the commas (e.g. pre-encode the query with
    quote(..., safe=",") rather than letting requests encode the dict).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions