{"record":{"id":"153040a7b26fe47f","repo":"BerriAI/litellm","slug":"both-project-id-and-topic-id-must-be-provided","errorCode":null,"errorMessage":"Both project_id and topic_id must be provided","messagePattern":"Both project_id and topic_id must be provided","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/integrations/gcs_pubsub/pub_sub.py","lineNumber":58,"sourceCode":"        Initialize Google Cloud Pub/Sub publisher\n\n        Args:\n            project_id (str): Google Cloud project ID\n            topic_id (str): Pub/Sub topic ID\n            credentials_path (str, optional): Path to Google Cloud credentials JSON file\n        \"\"\"\n        from litellm.proxy.utils import _premium_user_check\n\n        _premium_user_check()\n\n        self.async_httpx_client = get_async_httpx_client(llm_provider=httpxSpecialProvider.LoggingCallback)\n\n        self.project_id = project_id or os.getenv(\"GCS_PUBSUB_PROJECT_ID\")\n        self.topic_id = topic_id or os.getenv(\"GCS_PUBSUB_TOPIC_ID\")\n        self.path_service_account_json = credentials_path or os.getenv(\"GCS_PATH_SERVICE_ACCOUNT\")\n\n        if not self.project_id or not self.topic_id:\n            raise ValueError(\"Both project_id and topic_id must be provided\")\n\n        self.flush_lock = asyncio.Lock()\n        super().__init__(**kwargs, flush_lock=self.flush_lock)\n        asyncio.create_task(self.periodic_flush())\n        self.log_queue: list[SpendLogsPayload | StandardLoggingPayload] = []\n\n    async def construct_request_headers(self) -> dict[str, str]:\n        \"\"\"Construct authorization headers using Vertex AI auth\"\"\"\n        from litellm import vertex_chat_completion\n\n        (\n            _auth_header,\n            vertex_project,\n        ) = await vertex_chat_completion._ensure_access_token_async(\n            credentials=self.path_service_account_json,\n            project_id=self.project_id,\n            custom_llm_provider=\"vertex_ai\",\n        )","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/integrations/gcs_pubsub/pub_sub.py#L40-L76","documentation":"PubSub extended logging raises ValueError in __init__ when both project_id and topic_id cannot be resolved. Each falls back to env (GCS_PUBSUB_PROJECT_ID / GCS_PUBSUB_TOPIC_ID); the constructor runs a premium-user check first, then requires both values because publishing needs a fully-qualified topic.","triggerScenarios":"Instantiating the PubSub callback with neither constructor args nor env vars for project and topic — e.g. only GCS_PUBSUB_PROJECT_ID set, or callback name 'gcs_pubsub' enabled with no matching env at all.","commonSituations":"Env vars set in CI but not in the deployed proxy; typo'd var names; args swapped (topic passed as project).","solutions":["Set both env vars: GCS_PUBSUB_PROJECT_ID and GCS_PUBSUB_TOPIC_ID.","Or pass project_id= and topic_id= explicitly when constructing the callback.","Confirm a service account JSON (GCS_PATH_SERVICE_ACCOUNT) with pubsub publish rights is also configured."],"exampleFix":"# before\n# only GCS_PUBSUB_PROJECT_ID set\n\n# after\nexport GCS_PUBSUB_PROJECT_ID=my-project\nexport GCS_PUBSUB_TOPIC_ID=llm-logs","handlingStrategy":"validation","validationCode":"import os\n\nif \"gcs_pubsub\" in callbacks and not (os.getenv(\"GCS_PUBSUB_PROJECT_ID\") and os.getenv(\"GCS_PUBSUB_TOPIC_ID\")):\n    raise ValueError(\"GCS_PUBSUB_PROJECT_ID and GCS_PUBSUB_TOPIC_ID are both required for gcs_pubsub\")","typeGuard":"def pubsub_env_ready() -> bool:\n    import os\n    return bool(os.getenv(\"GCS_PUBSUB_PROJECT_ID\")) and bool(os.getenv(\"GCS_PUBSUB_TOPIC_ID\"))","tryCatchPattern":null,"preventionTips":["Preflight both env vars (plus GCS_PATH_SERVICE_ACCOUNT) before enabling the callback.","Copy exact variable names from docs — GCS_PUBSUB_PROJECT_ID, GCS_PUBSUB_TOPIC_ID.","Note this callback also requires a premium license (_premium_user_check runs first)."],"tags":["pubsub","env-vars","config","logging-callback","premium"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}