{"record":{"id":"aef17ed161cab62e","repo":"HKUDS/DeepTutor","slug":"self-name-publish-request-failed-exc","errorCode":null,"errorMessage":"{self.name}: publish request failed: {exc}","messagePattern":"(.+?): publish request failed: (.+?)","errorType":"http","errorClass":"HubError","httpStatus":null,"severity":"error","filePath":"deeptutor/services/skill/hub.py","lineNumber":474,"sourceCode":"        zip_bytes: bytes,\n        token: str,\n        fields: dict[str, str],\n    ) -> dict[str, Any]:\n        \"\"\"Publish a version via ``POST /skills`` (multipart + bearer token).\n\n        Read-only ClawHub mirrors will reject this; eduhub (same /api/v1 shape)\n        accepts it. Surfaces the API's JSON ``error`` message on failure.\n        \"\"\"\n        url = f\"{self._base_url}/skills\"\n        try:\n            response = self._client.post(\n                url,\n                data={\"slug\": slug, \"version\": version, **fields},\n                files={\"zip\": (\"package.zip\", zip_bytes, \"application/zip\")},\n                headers={\"Authorization\": f\"Bearer {token}\"},\n            )\n        except httpx.HTTPError as exc:\n            raise HubError(f\"{self.name}: publish request failed: {exc}\") from exc\n        if response.status_code >= 400:\n            detail = \"\"\n            try:\n                detail = str(response.json().get(\"error\") or \"\")\n            except ValueError:\n                detail = response.text[:200]\n            raise HubError(f\"{self.name}: publish failed (HTTP {response.status_code}): {detail}\")\n        try:\n            return response.json()\n        except ValueError:\n            return {}\n\n    def list_my_skills(self, token: str) -> list[dict[str, Any]]:\n        \"\"\"List the authenticated user's skills via ``GET /skills?owner=me``.\n\n        Each row carries the slug, current ``version`` (latest), the full\n        ``versions`` list (for rollback) and the current classification (for\n        pre-filling an upgrade's tagging) — see ``buildMySkills`` on the hub.","sourceCodeStart":456,"sourceCodeEnd":492,"githubUrl":"https://github.com/HKUDS/DeepTutor/blob/3e82f130422a813cdd73c10b21a44e9325f5821a/deeptutor/services/skill/hub.py#L456-L492","documentation":"Raised by ClawHubProvider.publish when the multipart POST to the hub's publish/upload endpoint fails at the transport level (httpx.HTTPError: connection refused, DNS failure, TLS error, timeout). No HTTP response was received.","triggerScenarios":"Calling publish(slug, version, token, ...) (via publish_to_hub / `skill publish`) while the hub host is unreachable, DNS fails, the TLS cert is invalid, or the upload of the large zip times out.","commonSituations":"Wrong base_url; corporate proxy blocking the POST; self-signed cert on a self-hosted hub; slow upload of a big skill zip exceeding the client timeout; offline environment.","solutions":["Verify connectivity: curl -v $BASE_URL (check DNS/TLS/proxy)","Increase the httpx client timeout for large skill zips","Fix base_url in settings/skill_hubs.json","Configure proxy env vars (HTTPS_PROXY) if behind a corporate proxy"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"resp = httpx.get(BASE.replace('/api',''), timeout=5)\nif resp.status_code >= 500: defer_publish()","typeGuard":null,"tryCatchPattern":"for attempt in range(3):\n    try:\n        return hub.publish(...)\n    except HubError as e:\n        if \"publish request failed\" in str(e) and attempt < 2:\n            time.sleep(2 ** attempt); continue\n        raise","preventionTips":["Set adequate httpx timeouts for zip uploads","Check connectivity before long publish flows"],"tags":["publish","network","timeout","hub"],"backgroundTag":"connection-error","analyzedSha":"3e82f130422a813cdd73c10b21a44e9325f5821a","analyzedAt":"2026-08-27T06:57:25.364Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}