{"record":{"id":"fd4d7d98aa475fea","repo":"gofr-dev/gofr","slug":"w-for-q-at-offset-d-w","errorCode":null,"errorMessage":"%w for %q at offset %d: %w","messagePattern":"%w for %q at offset (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/gofr/datasource/file/ftp/storage_adapter.go","lineNumber":136,"sourceCode":"\t}\n\n\tif offset < 0 {\n\t\treturn nil, fmt.Errorf(\"%w (got: %d)\", errInvalidOffset, offset)\n\t}\n\n\tif s.conn == nil {\n\t\treturn nil, errFTPClientNotInitialized\n\t}\n\n\tobjectPath := s.buildPath(name)\n\n\treader, err := s.conn.RetrFrom(objectPath, uint64(offset))\n\tif err != nil {\n\t\tif isFTPNotFoundError(err) {\n\t\t\treturn nil, fmt.Errorf(\"%w %q: %w\", errObjectNotFound, name, err)\n\t\t}\n\n\t\treturn nil, fmt.Errorf(\"%w for %q at offset %d: %w\", errFailedToCreateReader, name, offset, err)\n\t}\n\n\t// FTP doesn't support length limit in RetrFrom, so wrap in LimitReader\n\tif length > 0 {\n\t\treturn &limitedReadCloser{\n\t\t\tReader: io.LimitReader(reader, length),\n\t\t\tCloser: reader,\n\t\t}, nil\n\t}\n\n\treturn reader, nil\n}\n\n// limitedReadCloser combines io.LimitReader with Close capability.\ntype limitedReadCloser struct {\n\tio.Reader\n\tio.Closer\n}","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/gofr-dev/gofr/blob/187eb24962502e91f1fee856230670958b66e89c/pkg/gofr/datasource/file/ftp/storage_adapter.go#L118-L154","documentation":"NewRangeReader failed at the FTP level for a non-not-found reason: RetrFrom returned an error that isFTPNotFoundError did not match, so the library wraps errFailedToCreateReader along with the name, offset, and underlying error. Indicates connection/server problems or unsupported REST (restart) on the server.","triggerScenarios":"storageAdapter.NewRangeReader where s.conn.RetrFrom(objectPath, uint64(offset)) fails with errors like connection closed, 4xx/5xx server responses, or servers not supporting REST byte ranges.","commonSituations":"Stale/idle FTP connection dropped before the command, FTP server without REST support, offset beyond EOF causing a server-side error, permission issues.","solutions":["Verify the server supports REST (byte-range resume); otherwise read the whole object with NewReader and seek client-side","Check that offset < file size via StatObject before ranging","Re-dial/reconnect the FTP client and retry if the connection was idle-timed out","Inspect the wrapped error for the exact FTP response code","Check permissions for the authenticated FTP user"],"exampleFix":"// before\nr, err := store.NewRangeReader(ctx, \"big.bin\", 1<<40, 100) // offset beyond EOF\n// after\ninfo, _ := store.StatObject(ctx, \"big.bin\")\nif 1<<40 >= info.Size { return io.EOF }\nr, err := store.NewRangeReader(ctx, \"big.bin\", 1<<40, 100)","handlingStrategy":"retry","validationCode":"info, err := store.StatObject(ctx, name)\nif err != nil { return err }\nif offset >= info.Size { return io.EOF }","typeGuard":"func isFTPNotFound(err error) bool { return errors.Is(err, errObjectNotFound) }","tryCatchPattern":"r, err := store.NewRangeReader(ctx, name, offset, length)\nif err != nil && !errors.Is(err, errObjectNotFound) {\n    // reconnect and retry with backoff; check server REST support on repeated failure\n}","preventionTips":["Confirm the FTP server supports REST/Resume for ranged reads","Bound offsets by the object size from StatObject","Re-dial idle FTP connections before issuing ranged commands"],"tags":["ftp","network","range-request"],"backgroundTag":"ftp-retr-failed","analyzedSha":"187eb24962502e91f1fee856230670958b66e89c","analyzedAt":"2026-09-01T20:34:54.554Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}