Improve error handling and documentation across the SDK#1047
Draft
Improve error handling and documentation across the SDK#1047
Conversation
- Citrine class: add usage example, Raises section, explain each property's return type and available operations - exceptions.py: add module-level docstring explaining the exception hierarchy (retryable vs non-retryable) - All exception classes: expand one-line docstrings to explain what each exception means and what users should do about it - NonRetryableHttpException: document all public attributes - JobFailureError: document job_id and failure_reasons attrs Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- scores.py: add module docstring explaining the three score types and when to use each (LI for multi-objective sequential, EI for single-objective sequential, EV for no-baseline) - LIScore: explain "simultaneously exceeding" semantics - EIScore: clarify single-objective limit and magnitude focus - EVScore: explain equal-weight summing and how to influence relative weighting - Objectives: explain what descriptor_key must match - ScalarRangeConstraint: clarify inclusive/exclusive semantics and explain that violated constraints yield a zero score Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- DesignExecution: explain the execution lifecycle and link to Score, candidates(), and hierarchical_candidates() - candidates(): document return ordering (by score), per_page, and return type with full Parameters/Returns sections - hierarchical_candidates(): explain the difference from candidates() (includes process history and sub-materials) - predict(): document PredictRequest input and DesignCandidate return with full Parameters/Returns sections - PredictRequest: add full Parameters section documenting all 5 constructor arguments - DesignCandidate: explain primary_score semantics - DesignVariable: list all subtypes and when each is used - DesignCandidateComment: add missing class docstring Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- dimensions.py: add module docstring explaining role in design spaces; list all Dimension subtypes in base class - ContinuousDimension/IntegerDimension: explain default bound behavior (falls back to descriptor bounds) - EnumeratedDimension: explain use cases and value parsing - descriptors.py: add module docstring explaining role in the platform; list all 6 Descriptor subtypes in base class Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Module docstring: explain what data sources are and that GemTableDataSource is the most common type - DataSource base: list all 4 subtypes with brief descriptions - GemTableDataSource: explain what GEM Tables are and how to find table IDs and versions Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Collection class: explain available CRUD operations and that concrete subclasses may add more - get(): add Parameters, Returns, and Raises sections - register(): add Parameters, Returns, and Raises sections - update(): add Parameters and Returns sections - delete(): add Parameters and Returns sections Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All four Shapley classes had minimal (1-line) docstrings with no explanation of what Shapley values are or how to interpret them. Now: - Module docstring: explain Shapley values, positive/negative semantics, and the class hierarchy - ShapleyMaterial: document material_id and value attributes - ShapleyFeature: document feature name and materials list - ShapleyOutput: document output name and features list - FeatureEffects: document all attributes including status, failure_reason, and link to as_dict convenience property Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- JobSubmissionResponse: explain what it is and how to use job_id for status polling - waiting.py: add module docstring explaining polling utilities - ConditionTimeoutError: explain that the server continues running independently and suggest increasing timeout Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix copy-paste bug in migrate_deprecated_argument where both sides of the error message showed new_arg_name instead of old_arg_name - Replace bare Exception with TypeError in validate_type for clearer error semantics - Fix NotFound.build() lambda signature (lambda self: -> lambda:) that silently prevented api_error from being populated - Fix "Cant" typo in WorkflowNotReadyException message Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Extract x-request-id or x-correlation-id from response headers and store as request_id attribute. Also store the HTTP method. Both are included in the error message for easier debugging and support escalation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace silent ValueError pass with logger.debug for 401 JSON parsing (was completely invisible to users/developers) - Downgrade AttributeError from logger.error to logger.debug (this is an expected case, not a true error) - Upgrade JSONDecodeError in _extract_response_json from logger.info to logger.warning (returning empty dict silently can cause confusing downstream failures) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add 'from e' to exception re-raises in collection.py and ingestion.py so the original cause is preserved in tracebacks - Replace 'raise e' with bare 'raise' to preserve traceback context when re-raising the same exception - Add logger.warning in pageable.py when response data is not a dict (was silently swallowed, hiding type errors) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- PollingTimeoutError now includes job_id, timeout duration, and explains the server-side job continues running - ConditionTimeoutError now explains client timeout is independent of server-side work and suggests increasing timeout or polling manually Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Batcher collision error now explains what a collision means and suggests ensuring unique UIDs - Batcher dependency error now shows count and first 10 dependency names, suggests increasing batch_size - Collection uid=None error now explains the likely cause (unregistered object) and suggests calling .register() - Deserialization errors truncate data dicts to 200 chars and value reprs to 100 chars to avoid overwhelming output Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add validation_errors property and has_failure() method to
NonRetryableHttpException for structured access to API
validation errors without parsing message strings.
Enables patterns like:
except BadRequest as e:
for ve in e.validation_errors:
print(f"Field '{ve.property}': {ve.failure_message}")
if e.has_failure("missing_required_field"):
# handle specifically
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add optional 'hint' keyword argument to CitrineException that appends actionable guidance to error messages. When present, __str__ outputs the base message followed by "\n\nHint: <hint>". This is the foundation for adding actionable hints to all exception subclasses in subsequent PRs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace bare CitrineException(response.text) for 5xx errors with a structured ServerError that includes method, path, status code, response text (truncated to 500 chars), request ID, and an actionable hint about contacting support. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Each HTTP exception subclass now has a _default_hint providing actionable guidance: - NotFound: verify resource UID - Unauthorized: check API key validity - BadRequest: check validation errors - WorkflowConflictException: wait and retry Hints are wired through NonRetryableHttpException.__init__ to the base CitrineException hint mechanism. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
UnauthorizedRefreshToken now includes a descriptive message and hint directing users to regenerate their API key at the platform URL or set the CITRINE_API_KEY environment variable. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Comprehensive improvements to error handling and docstrings across the citrine-python SDK.
Error Handling
migrate_deprecated_argument, bareException→TypeError,NotFound.build()lambda signature, "Cant" typoCitrineExceptionbase class now accepts an optionalhintkwarg appended to error messages as actionable guidancemethod,path,status_code,response_text,request_idattributesNonRetryableHttpExceptionextractsx-request-idfrom response headers for support escalationNotFound,Unauthorized,BadRequest,Conflicteach include actionable guidancepass/logger.infowithlogger.debug/logger.warningin_session.pyandpageable.pyfrom eto re-raises incollection.pyandingestion.pyPollingTimeoutErrorandConditionTimeoutErrornow explain server continues running and suggest increasing timeoutuid=None, deserialization errors all improved with context and suggestionsvalidation_errorsproperty andhas_failure()method onNonRetryableHttpExceptionUnauthorizedRefreshTokenincludes host URL for key regenerationDocumentation
Citrineclass with usage example, Raises section, property return typescandidates(),hierarchical_candidates(),predict()all documented with Parameters/Returnsprimary_scoresemanticsGemTableDataSourceusage guidanceJobSubmissionResponseattributes,ConditionTimeoutErrorguidanceTest plan
🤖 Generated with Claude Code