{"record":{"id":"0393d85740ffb562","repo":"AlistGo/alist","slug":"file-is-nil","errorCode":null,"errorMessage":"file is nil","messagePattern":"file is nil","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/guangyapan/driver.go","lineNumber":382,"sourceCode":"\t}, &out); err != nil {\n\t\treturn err\n\t}\n\tif !strings.EqualFold(strings.TrimSpace(out.Msg), \"success\") {\n\t\treturn fmt.Errorf(\"copy failed: %s\", strings.TrimSpace(out.Msg))\n\t}\n\ttaskID := strings.TrimSpace(out.Data.TaskID)\n\tif taskID == \"\" {\n\t\treturn nil\n\t}\n\treturn d.waitTaskDone(ctx, taskID)\n}\n\nfunc (d *GuangYaPan) Put(ctx context.Context, dstDir model.Obj, file model.FileStreamer, up driver.UpdateProgress) error {\n\tif err := d.ensureAccessToken(ctx); err != nil {\n\t\treturn err\n\t}\n\tif file == nil {\n\t\treturn errors.New(\"file is nil\")\n\t}\n\tif file.GetSize() < 0 {\n\t\treturn errors.New(\"invalid file size\")\n\t}\n\tname := strings.TrimSpace(file.GetName())\n\tif name == \"\" {\n\t\treturn errors.New(\"file name is empty\")\n\t}\n\n\tparentID := dstDir.GetID()\n\n\ttoken, code, err := d.getUploadToken(ctx, parentID, name, file.GetSize())\n\tif err != nil {\n\t\treturn err\n\t}\n\ttaskID := strings.TrimSpace(token.TaskID)\n\tif code == 156 {\n\t\tif taskID == \"\" {","sourceCodeStart":364,"sourceCodeEnd":400,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/drivers/guangyapan/driver.go#L364-L400","documentation":"GuangYaPan Put guards against a nil model.FileStreamer before using it. A nil stream means the upload request itself is malformed — no file payload reached the driver — so it aborts before requesting an upload token.","triggerScenarios":"Programmatically invoking Put with a nil file argument; upstream proxying code that failed to construct the streamer (e.g. a multipart parse failure swallowed earlier) and passed nil through.","commonSituations":"Custom integrations calling the driver directly; bugs in middleware that forwards uploads; nil returned by a stream constructor on error and not checked.","solutions":["Check the caller: ensure the streamer is built and non-nil before Put","If a stream constructor returns (nil, err), handle err instead of continuing","Reproduce with a normal UI upload; if that works, the bug is in the custom caller"],"exampleFix":"// before\nstream, err := NewStreamer(r)\n_ = err // ignored; stream may be nil\nd.Put(ctx, dir, stream, up)\n// after\nstream, err := NewStreamer(r)\nif err != nil { return err }\nreturn d.Put(ctx, dir, stream, up)","handlingStrategy":"validation","validationCode":"if file == nil {\n\treturn errors.New(\"upload aborted: no file stream provided\")\n}\nreturn d.Put(ctx, dstDir, file, up)","typeGuard":"func hasStream(f model.FileStreamer) bool { return f != nil }","tryCatchPattern":"stream, err := buildStreamer(req)\nif err != nil { return err }\nif stream == nil { return errors.New(\"internal: stream construction returned nil\") }\nreturn d.Put(ctx, dstDir, stream, up)","preventionTips":["Never ignore errors from stream constructors — check both value and error","Add integration tests that assert non-nil streamers before Put","Validate multipart form parsing before forwarding to the driver"],"tags":["guangyapan","upload","nil-check","driver"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}