{"record":{"id":"a0cd3053bed02ff5","repo":"thanos-io/thanos","slug":"ulid-q-is-not-valid-v","errorCode":null,"errorMessage":"ULID %q is not valid: %v","messagePattern":"ULID %q is not valid: (.+?)","errorType":"http","errorClass":"ApiError","httpStatus":400,"severity":"error","filePath":"pkg/api/blocks/v1.go","lineNumber":114,"sourceCode":"func (bapi *BlocksAPI) markBlock(r *http.Request) (any, []error, *api.ApiError, func()) {\n\tif bapi.disableAdminOperations {\n\t\treturn nil, nil, &api.ApiError{Typ: api.ErrorBadData, Err: errors.New(\"Admin operations are disabled\")}, func() {}\n\t}\n\tidParam := r.FormValue(\"id\")\n\tactionParam := r.FormValue(\"action\")\n\tdetailParam := r.FormValue(\"detail\")\n\n\tif idParam == \"\" {\n\t\treturn nil, nil, &api.ApiError{Typ: api.ErrorBadData, Err: errors.New(\"ID cannot be empty\")}, func() {}\n\t}\n\n\tif actionParam == \"\" {\n\t\treturn nil, nil, &api.ApiError{Typ: api.ErrorBadData, Err: errors.New(\"Action cannot be empty\")}, func() {}\n\t}\n\n\tid, err := ulid.Parse(idParam)\n\tif err != nil {\n\t\treturn nil, nil, &api.ApiError{Typ: api.ErrorBadData, Err: errors.Errorf(\"ULID %q is not valid: %v\", idParam, err)}, func() {}\n\t}\n\n\tactionType := parse(actionParam)\n\tswitch actionType {\n\tcase Deletion:\n\t\terr := block.MarkForDeletion(r.Context(), bapi.logger, bapi.bkt, id, detailParam, promauto.With(nil).NewCounter(prometheus.CounterOpts{}))\n\t\tif err != nil {\n\t\t\treturn nil, nil, &api.ApiError{Typ: api.ErrorBadData, Err: err}, func() {}\n\t\t}\n\tcase NoCompaction:\n\t\terr := block.MarkForNoCompact(r.Context(), bapi.logger, bapi.bkt, id, metadata.ManualNoCompactReason, detailParam, promauto.With(nil).NewCounter(prometheus.CounterOpts{}))\n\t\tif err != nil {\n\t\t\treturn nil, nil, &api.ApiError{Typ: api.ErrorBadData, Err: err}, func() {}\n\t\t}\n\tdefault:\n\t\treturn nil, nil, &api.ApiError{Typ: api.ErrorBadData, Err: errors.Errorf(\"not supported marker %v\", actionParam)}, func() {}\n\t}\n\treturn nil, nil, nil, func() {}","sourceCodeStart":96,"sourceCodeEnd":132,"githubUrl":"https://github.com/thanos-io/thanos/blob/35b8b991177def87ed52dcf10f9b6d87f07282c8/pkg/api/blocks/v1.go#L96-L132","documentation":"markBlock validates that the 'id' URL parameter of the block mark endpoint is a valid ULID (Thanos block IDs are ULIDs). If ulid.Parse fails, the request is rejected with ErrorBadData carrying the parse failure detail. It means the caller supplied a block ID that is not a well-formed ULID string.","triggerScenarios":"Calling POST/GET /api/v1/blocks/<id>/<action> (or markBlock via the blocks API) with an id param that is empty of ULID structure, e.g. a plain name like 'myblock', a truncated/typoed ULID, or a Prometheus TSDB directory path instead of a block ID.","commonSituations":"Scripting against the Thanos Query/Store blocks API with hand-written IDs; copying bucket paths instead of ULIDs; using old block IDs from a different TSDB layout; shell variable interpolation dropping characters from the ID.","solutions":["Print the ID and validate it against a ULID regex (26 chars, Crockford base32) before sending","List actual blocks via the blocks list API or bucket inspection to get a valid ID","Check for shell quoting/interpolation issues that mangled the ID","Ensure you are using the block ULID, not the block directory path including parent folders"],"exampleFix":"// before\ncurl -X POST host/api/v1/blocks/bucket-01/no-compact\n// after\ncurl -X POST host/api/v1/blocks/01ARZ3NDEKTSV4RRFFQ69G5FAV/no-compact","handlingStrategy":"validation","validationCode":"const ulidRe = /^[0-9A-HJKMNP-TV-Z]{26}$/;\nfunction isValidULID(id) { return ulidRe.test(id); }\nif (!isValidULID(blockID)) throw new Error(`not a ULID: ${blockID}`);","typeGuard":"function isULID(s) { return typeof s === 'string' && /^[0-9A-HJKMNP-TV-Z]{26}$/.test(s); }","tryCatchPattern":"try {\n  const res = await fetch(`/api/v1/blocks/${id}/${action}`, {method:'POST'});\n  const body = await res.json();\n  if (body.errorType === 'bad_data') throw new Error(body.error);\n} catch (e) {\n  if (/ULID .* is not valid/.test(e.message)) { /* re-prompt for valid block ID */ }\n  throw e;\n}","preventionTips":["Validate IDs against the ULID regex before calling the mark endpoint","Fetch block IDs from the blocks list API instead of typing them","Beware shell interpolation/quoting when composing URLs","Never pass bucket paths as block IDs"],"tags":["http-api","ulid","validation","thanos"],"backgroundTag":"invalid-argument-format","analyzedSha":"35b8b991177def87ed52dcf10f9b6d87f07282c8","analyzedAt":"2026-09-07T01:49:59.689Z","contentChangedAt":"2026-09-07T01:49:59.689Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}