{"record":{"id":"a87b3bdf9f5a00dc","repo":"AlistGo/alist","slug":"file-name-must-not-empty","errorCode":null,"errorMessage":"file_name must not empty","messagePattern":"file_name must not empty","errorType":"validation","errorClass":null,"httpStatus":400,"severity":"warning","filePath":"server/handles/label_file_binding.go","lineNumber":35,"sourceCode":"\tFileName string `json:\"file_name\"`\n\tLabelId  string `json:\"label_id\"`\n}\n\ntype pageResp[T any] struct {\n\tContent []T   `json:\"content\"`\n\tTotal   int64 `json:\"total\"`\n}\n\ntype restoreLabelBindingsReq struct {\n\tKeepIDs  bool                     `json:\"keep_ids\"`\n\tOverride bool                     `json:\"override\"`\n\tBindings []model.LabelFileBinding `json:\"bindings\"`\n}\n\nfunc GetLabelByFileName(c *gin.Context) {\n\tfileName := c.Query(\"file_name\")\n\tif fileName == \"\" {\n\t\tcommon.ErrorResp(c, errors.New(\"file_name must not empty\"), 400)\n\t\treturn\n\t}\n\tdecodedFileName, err := url.QueryUnescape(fileName)\n\tif err != nil {\n\t\tcommon.ErrorResp(c, errors.New(\"invalid file_name\"), 400)\n\t\treturn\n\t}\n\tfmt.Println(\">>> 原始 fileName:\", fileName)\n\tfmt.Println(\">>> 解码后 fileName:\", decodedFileName)\n\tuserObj, ok := c.Value(\"user\").(*model.User)\n\tif !ok {\n\t\tcommon.ErrorStrResp(c, \"user invalid\", 401)\n\t\treturn\n\t}\n\tlabels, err := op.GetLabelByFileName(userObj.ID, decodedFileName)\n\tif err != nil {\n\t\tcommon.ErrorResp(c, err, 500, true)\n\t\treturn","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/server/handles/label_file_binding.go#L17-L53","documentation":"Returned by GetLabelByFileName (server/handles/label_file_binding.go:36-39) when the required 'file_name' query parameter is missing or empty. The handler reads c.Query(\"file_name\"), rejects empty values with HTTP 400, then URL-decodes the value for the lookup. Note the handler also contains leftover debug fmt.Println statements (Chinese-prefixed) that leak the raw and decoded filename to stdout on every call.","triggerScenarios":"Calling the label-by-file endpoint without ?file_name=... or with ?file_name= (empty value).","commonSituations":"Frontend builds the URL from a variable that is undefined for virtual/root paths; curl invocations forgetting the query string; URL-encoding bugs that collapse the parameter to empty.","solutions":["Pass a non-empty file_name query parameter, URL-encoded: ?file_name=%2Fpath%2Fto%2Ffile","Check client-side that the path variable is defined before issuing the request","Operators: remove the debug fmt.Println lines (they log every queried filename)"],"exampleFix":"// before\nGET /api/label/file\n// after\nGET /api/label/file?file_name=%2Fdocs%2Freport.pdf","handlingStrategy":"validation","validationCode":"if fileName == \"\" {\n    return errors.New(\"file_name query parameter is required\")\n}\nurl := base + \"/api/label/file?file_name=\" + url.QueryEscape(fileName)","typeGuard":null,"tryCatchPattern":"if resp.StatusCode() == 400 && strings.Contains(resp.String(), \"file_name must not empty\") {\n    // caller bug: request URL was built without the query param — fix at the call site\n}","preventionTips":["Assert required query params in a shared request-builder instead of ad-hoc string concat","Beware: gin decodes once, this handler decodes again — escape '%' as '%25'","Remove the handler's leftover debug fmt.Println lines in production builds"],"tags":["labels","http-api","validation","query-params"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}