{"record":{"id":"334fe47aabae1e07","repo":"thanos-io/thanos","slug":"id-cannot-be-empty","errorCode":null,"errorMessage":"ID cannot be empty","messagePattern":"ID cannot be empty","errorType":"http","errorClass":"ApiError","httpStatus":400,"severity":"error","filePath":"pkg/api/blocks/v1.go","lineNumber":105,"sourceCode":"func (bapi *BlocksAPI) Register(r *route.Router, tracer opentracing.Tracer, logger log.Logger, ins extpromhttp.InstrumentationMiddleware, logMiddleware *logging.HTTPServerMiddleware) {\n\tbapi.baseAPI.Register(r, tracer, logger, ins, logMiddleware)\n\n\tinstr := api.GetInstr(tracer, logger, ins, logMiddleware, bapi.disableCORS)\n\n\tr.Get(\"/blocks\", instr(\"blocks\", bapi.blocks))\n\tr.Post(\"/blocks/mark\", instr(\"blocks_mark\", bapi.markBlock))\n}\n\nfunc (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}","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/thanos-io/thanos/blob/35b8b991177def87ed52dcf10f9b6d87f07282c8/pkg/api/blocks/v1.go#L87-L123","documentation":"markBlock requires the form parameter 'id' identifying the block ULID. When the request omits it (or it is an empty string), the API rejects the request with an ErrorBadData ApiError 'ID cannot be empty'.","triggerScenarios":"POST /api/v1/blocks/mark without the id form field, or with id= (empty value).","commonSituations":"curl calls missing -d 'id=...'; automation building the form body with an empty variable because the block ID lookup failed upstream.","solutions":["Send the id form field with the block ULID: curl -X POST -d 'id=01ARZ3NDEKTSV4RRFFQ69G5FAV' ... .","Verify the upstream step that produces the block ID actually returned a value before calling the API.","Add client-side validation that id is a non-empty ULID before issuing the request."],"exampleFix":"// before\ncurl -X POST http://thanos:9090/api/v1/blocks/mark -d 'action=deletion'\n// after\ncurl -X POST http://thanos:9090/api/v1/blocks/mark -d 'action=deletion' -d 'id=01ARZ3NDEKTSV4RRFFQ69G5FAV'","handlingStrategy":"validation","validationCode":"if blockID == \"\" {\n    return errors.New(\"cannot call /blocks/mark without a block ULID id\")\n}\nif _, err := ulid.Parse(blockID); err != nil {\n    return fmt.Errorf(\"invalid ULID %q: %w\", blockID, err)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Assert the block ID exists (list blocks first) before marking","Use ULID parsing client-side to catch malformed IDs early","Never build form bodies from possibly-empty variables without checks"],"tags":["http","api","validation"],"backgroundTag":"missing-required-argument","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"}