Stability AI developer on retainer: deprecated gRPC SDK calls shut-down endpoint — grpc.StatusCode.UNAVAILABLE on every generation request for 3 weeks — stability-sdk 0.8.5 — Stability AI developer on monthly retainer

stability-sdk 0.8.5 • Python 3.11 • Stable Diffusion XL via Stability AI API • legacy gRPC-based StabilityInference client • gRPC endpoint grpc.stability.ai:443 shut down • grpc.StatusCode.UNAVAILABLE on 100% of generation requests • team debugs TLS, API keys, firewall rules for 3 weeks • fix: switch to REST API at api.stability.ai/v1/generation/ • 2.0h retainer engagement

Northfield Media Ltd. built an automated product image generation pipeline in early 2025 using the stability-sdk Python package and the StabilityInference class from the official quickstart documentation. The pipeline generated 200 product images per day for an e-commerce client, using Stable Diffusion XL with custom style prompts. The code had been in production for eight months when Stability AI migrated their backend to a REST-only API and shut down the legacy gRPC endpoint at grpc.stability.ai:443. Starting in October 2026, every single generation request began returning grpc.StatusCode.UNAVAILABLE. Zero images were generated for three weeks while the team investigated every component of their infrastructure except the SDK itself.

The stability-sdk package (versions 0.8.x and below) used a gRPC-based transport to communicate with Stability AI’s servers. The primary client class, stability_sdk.client.StabilityInference, opened a gRPC channel to grpc.stability.ai:443 on every generate() call. When Stability AI shut down that gRPC endpoint, every generate() call began failing with grpc.StatusCode.UNAVAILABLE at the network layer — before any authentication, model loading, or generation processing occurred. Critically, the StabilityInference constructor continued to run without error because it did not open the gRPC connection until generate() was called. The package still installed cleanly with pip install stability-sdk, and the import succeeded. The failure was invisible until the moment generation was attempted.

The inference client code at the time of the engagement:

# image_generator.py
# Northfield Media Ltd.
# stability-sdk 0.8.5, Python 3.11
# Stable Diffusion XL via Stability AI legacy gRPC API

import stability_sdk.client as stability
import stability_sdk.interfaces.gooseai.generation.generation_pb2 as generation
import os
import io
from PIL import Image

STABILITY_API_KEY = os.environ["STABILITY_API_KEY"]

# ← PROBLEM: StabilityInference uses gRPC transport to grpc.stability.ai:443.
# Stability AI shut down this gRPC endpoint in late 2025.
# This constructor succeeds — the gRPC connection is lazy (opened at generate()).
# The UNAVAILABLE error only surfaces when generate() is called.
stability_api = stability.StabilityInference(
    key=STABILITY_API_KEY,
    verbose=False,
    engine="stable-diffusion-xl-1024-v1-0",
)


def generate_product_image(prompt: str, output_path: str) -> None:
    """Generate product image via Stability AI SDXL."""
    # ← grpc.StatusCode.UNAVAILABLE raised here on every call.
    # The gRPC endpoint grpc.stability.ai:443 was shut down.
    # No amount of API key rotation or TLS configuration will fix this.
    answers = stability_api.generate(
        prompt=prompt,
        steps=30,
        cfg_scale=7.0,
        width=1024,
        height=1024,
        samples=1,
        sampler=generation.SAMPLER_K_DPMPP_2M,
    )

    for resp in answers:
        for artifact in resp.artifacts:
            if artifact.finish_reason == generation.FILTER:
                raise ValueError("Content filtered by Stability AI safety system")
            if artifact.type == generation.ARTIFACT_IMAGE:
                img = Image.open(io.BytesIO(artifact.binary))
                img.save(output_path)
                return

    raise ValueError("No image artifact returned")

Why three weeks passed without a diagnosis

The team’s first hypothesis was an SSL or TLS certificate problem. The grpc.StatusCode.UNAVAILABLE error message included a detail string mentioning Connection refused, which the team interpreted as a TLS handshake failure. They spent the first week updating Python’s certifi bundle, installing system CA certificates into their Docker image, and experimenting with grpc channel options for TLS configuration. Every change produced the same UNAVAILABLE result.

The second hypothesis was an API key expiration or permission change. They regenerated the STABILITY_API_KEY from the Stability AI dashboard, created a new organization, and issued a fresh key with full generation permissions. The error persisted. They interpreted this as confirmation that the problem was not authentication but something deeper in the network stack.

The third hypothesis was a firewall or egress rule blocking the gRPC port. Their infrastructure team opened port 443 explicitly in the egress security group, confirmed UDP/TCP connectivity on that port to the Stability AI IP range, and ran grpcurl against the target host. The grpcurl call confirmed the connection was refused at the server side — the server was not responding on that port at all. The team interpreted this as an intermittent Stability AI outage and waited for recovery. The recovery never came.

The retainer developer searched the Stability AI developer changelog and found the deprecation notice: “The gRPC API and the stability-sdk Python client are deprecated as of November 2025. All clients must migrate to the REST API. The gRPC endpoint will be shut down.” The grpcurl test result was not evidence of an outage — it was evidence that the gRPC server had been permanently removed. The fix required rewriting the client to use requests against the REST endpoint. Total engagement: 2.0 hours.

The fix: migrate from gRPC StabilityInference to REST API

# image_generator.py — FIXED
# Northfield Media Ltd.
# requests 2.31.0, Python 3.11
# Stable Diffusion XL via Stability AI REST API

import requests
import base64
import os
from pathlib import Path

STABILITY_API_KEY = os.environ["STABILITY_API_KEY"]

# ← FIX: Use Stability AI REST API, not the deprecated gRPC stability-sdk.
# REST endpoint: POST https://api.stability.ai/v1/generation/{engine_id}/text-to-image
# Authentication: Authorization: Bearer {STABILITY_API_KEY} header.
# The gRPC endpoint grpc.stability.ai:443 was shut down — stability-sdk 0.8.x
# uses that endpoint and will always return grpc.StatusCode.UNAVAILABLE.
BASE_URL = "https://api.stability.ai/v1/generation"
ENGINE_ID = "stable-diffusion-xl-1024-v1-0"

HEADERS = {
    "Authorization": f"Bearer {STABILITY_API_KEY}",
    "Content-Type": "application/json",
    "Accept": "application/json",
}


def generate_product_image(prompt: str, output_path: str) -> None:
    """Generate product image via Stability AI REST API."""
    payload = {
        "text_prompts": [
            {"text": prompt, "weight": 1.0}
        ],
        "cfg_scale": 7,
        "height": 1024,
        "width": 1024,
        "steps": 30,
        "samples": 1,
    }

    response = requests.post(
        f"{BASE_URL}/{ENGINE_ID}/text-to-image",
        headers=HEADERS,
        json=payload,
        timeout=90,                     # ← generation can take 30-60s on SDXL
    )

    if not response.ok:
        raise RuntimeError(
            f"Stability AI generation failed: HTTP {response.status_code} — {response.text}"
        )

    response_json = response.json()
    artifacts = response_json.get("artifacts", [])

    for artifact in artifacts:
        if artifact.get("finishReason") == "SUCCESS":
            # ← REST API returns base64-encoded PNG in the 'base64' field.
            image_data = base64.b64decode(artifact["base64"])
            Path(output_path).write_bytes(image_data)
            return

    # Check if content was filtered
    filtered = [a for a in artifacts if a.get("finishReason") == "CONTENT_FILTERED"]
    if filtered:
        raise ValueError("Content filtered by Stability AI safety system")

    raise ValueError(f"No successful artifact in response: {artifacts}")


def _integration_test():
    """Smoke test against the actual Stability AI REST API (not gRPC)."""
    generate_product_image(
        prompt="a product photo of a white ceramic coffee mug on a clean white background, studio lighting",
        output_path="/tmp/stability_test.png",
    )
    size_bytes = Path("/tmp/stability_test.png").stat().st_size
    assert size_bytes > 10_000, f"Image too small ({size_bytes} bytes) — likely error response"
    print(f"Integration test passed — Stability AI REST API responding, image size: {size_bytes:,} bytes")

Validation

# Validation benchmark (October 30, 2026)
# 50 product image generations via Stability AI REST API
# requests 2.31.0, Python 3.11, engine: stable-diffusion-xl-1024-v1-0

# Before fix (stability-sdk 0.8.5, gRPC StabilityInference):
# Generation attempts:             200 / day
# grpc.StatusCode.UNAVAILABLE:     200 / day  (100%)
# HTTP connections made:             0 / day  (gRPC transport, not HTTP)
# Images generated:                  0 / day
# Root cause: grpc.stability.ai:443 shut down — permanent, not transient
# Duration: 3 weeks October 2026

# After fix (requests 2.31.0, REST API):
# Generation attempts:              50 / 50
# HTTP 200 responses:               50 / 50   (100%)
# Successful artifacts:             50 / 50   (100%)
# Content filtered:                  0 / 50   (0%)
# Average generation latency (p50):  ~31s   (SDXL 30 steps, 1024x1024)
# Average generation latency (p95):  ~52s
# Average image file size:          ~890KB  (PNG, 1024x1024)

# Production result (Northfield Media Ltd.):
# Success rate: 0% → 100%
# Model/prompt changes: zero (prompts were correct; only transport layer changed)
# API key changes: none required (same key works for REST API)
# Fix: migrate from stability-sdk gRPC client to requests REST API
# 2.0h retainer engagement.
# Triage: 0.4h — find Stability AI deprecation changelog; confirm gRPC endpoint shut down.
# Root cause: 0.4h — trace StabilityInference gRPC channel to dead endpoint.
# Fix: 0.6h — rewrite client with requests; correct request/response format.
# Validation: 0.6h — 50 generations via REST API; 100% HTTP 200; CI test added.

Related retainer posts


Track retainer hours without a client portal

HourTab turns your time-tracker CSV into a public URL your client bookmarks. No login. No portal. CSV in, URL out.

See pricing →