Describe the bug
ReadStreamUtils.url_to_stream fetches a URL and returns its body without checking the HTTP status:
# deepinfra/utils/read_stream.py
response = httpx.get(url, follow_redirects=True)
return BytesIO(response.content)
If the URL 404s (or 500s, or returns a login page), the error page's bytes become the "file". FormDataUtils.get_form_data then uploads that HTML as the blob field, so AutomaticSpeechRecognition.generate({"audio": url, ...}) sends an HTML document where the audio should be. The user sees either a confusing model-side error or a bad result, with nothing pointing at the URL that failed.
This is the one place in the SDK where a failed HTTP response is neither raised nor surfaced: the client in deepinfra/clients/deepinfra.py maps every error status onto the APIStatusError hierarchy in _exceptions.py, and file_to_stream lets a missing local path raise FileNotFoundError. A dead URL is the same class of mistake as a wrong path, but it fails silently instead.
Steps to reproduce
import http.server, threading
from deepinfra.utils.read_stream import ReadStreamUtils
class Handler(http.server.BaseHTTPRequestHandler):
def do_GET(self):
body = b"<html><body><h1>404 Not Found</h1></body></html>"
self.send_response(404)
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
def log_message(self, *a): pass
srv = http.server.HTTPServer(("127.0.0.1", 0), Handler)
threading.Thread(target=srv.serve_forever, daemon=True).start()
url = f"http://127.0.0.1:{srv.server_address[1]}/missing-audio.mp3"
print(ReadStreamUtils.get_read_stream(url).read())
Output on deepinfra 0.3.0:
b'<html><body><h1>404 Not Found</h1></body></html>'
The same bytes reach the request body through FormDataUtils.get_form_data({"audio": url}, blob_keys=["audio"]).
Expected behaviour
A failed download should raise, with the URL and status in the message, rather than producing a stream of the error page.
Suggested fix
Call response.raise_for_status() and translate the failure into the SDK's own error type, so callers can catch it alongside every other SDK failure:
response = httpx.get(url, follow_redirects=True, timeout=...)
if response.is_error:
raise APIStatusError(
f"Failed to download {url}",
status_code=response.status_code,
response=response,
)
A transport failure (DNS, connect, TLS) would similarly map to APIConnectionError, matching _map_transport_error in the client.
Happy to send a PR with this and a regression test if the approach looks right.
Smaller, related points in the same file, happy to split out or leave
get_read_stream treats any string starting with http as a URL, so a local file named http_notes.wav is fetched as a URL.
- A
data: URI without a comma raises IndexError from input_data.split(",")[1] rather than a clear error.
BaseModel._warn_about_missing_api_key prints a warning and returns "", so a missing key sends Authorization: Bearer and surfaces as a server-side 401 instead of the SDK's own AuthenticationError, whose message tells the user exactly which environment variable to set.
Environment
deepinfra 0.3.0 (main at 3a6c0b9), Python 3.12, macOS.
Describe the bug
ReadStreamUtils.url_to_streamfetches a URL and returns its body without checking the HTTP status:If the URL 404s (or 500s, or returns a login page), the error page's bytes become the "file".
FormDataUtils.get_form_datathen uploads that HTML as the blob field, soAutomaticSpeechRecognition.generate({"audio": url, ...})sends an HTML document where the audio should be. The user sees either a confusing model-side error or a bad result, with nothing pointing at the URL that failed.This is the one place in the SDK where a failed HTTP response is neither raised nor surfaced: the client in
deepinfra/clients/deepinfra.pymaps every error status onto theAPIStatusErrorhierarchy in_exceptions.py, andfile_to_streamlets a missing local path raiseFileNotFoundError. A dead URL is the same class of mistake as a wrong path, but it fails silently instead.Steps to reproduce
Output on deepinfra 0.3.0:
The same bytes reach the request body through
FormDataUtils.get_form_data({"audio": url}, blob_keys=["audio"]).Expected behaviour
A failed download should raise, with the URL and status in the message, rather than producing a stream of the error page.
Suggested fix
Call
response.raise_for_status()and translate the failure into the SDK's own error type, so callers can catch it alongside every other SDK failure:A transport failure (DNS, connect, TLS) would similarly map to
APIConnectionError, matching_map_transport_errorin the client.Happy to send a PR with this and a regression test if the approach looks right.
Smaller, related points in the same file, happy to split out or leave
get_read_streamtreats any string starting withhttpas a URL, so a local file namedhttp_notes.wavis fetched as a URL.data:URI without a comma raisesIndexErrorfrominput_data.split(",")[1]rather than a clear error.BaseModel._warn_about_missing_api_keyprints a warning and returns"", so a missing key sendsAuthorization: Bearerand surfaces as a server-side 401 instead of the SDK's ownAuthenticationError, whose message tells the user exactly which environment variable to set.Environment
deepinfra 0.3.0 (main at 3a6c0b9), Python 3.12, macOS.