Repository navigation
feat(hints)!: give every error one hint for the SDK and one for the CLI - #698
Merged
Merged
Conversation
This was referenced Nov 6, 2026
karhu
force-pushed
the
tnet-157/21-hints
branch
from
November 6, 2026 10:35
e2e63c8 to
f9d1c80
Compare
karhu
force-pushed
the
tnet-157/21-hints
branch
from
November 6, 2026 10:57
f9d1c80 to
8febc08
Compare
karhu
marked this pull request as ready for review
November 6, 2026 13:11
karhu
force-pushed
the
tnet-157/21-hints
branch
from
November 9, 2026 11:11
e357bc3 to
1fdb781
Compare
TimoStoff
approved these changes
Nov 9, 2026
karhu
force-pushed
the
tnet-157/21-hints
branch
from
November 9, 2026 12:23
1fdb781 to
8f39064
Compare
karhu
force-pushed
the
tnet-157/21-hints
branch
from
November 9, 2026 13:56
8f39064 to
cfd2fbf
Compare
karhu
force-pushed
the
tnet-157/21-hints
branch
from
November 9, 2026 15:06
cfd2fbf to
7d4c7b7
Compare
karhu
force-pushed
the
tnet-157/21-hints
branch
2 times, most recently
from
November 9, 2026 16:50
4917142 to
518ce17
Compare
karhu
force-pushed
the
tnet-157/21-hints
branch
from
November 9, 2026 18:57
518ce17 to
df62a91
Compare
karhu
force-pushed
the
tnet-157/21-hints
branch
from
November 9, 2026 19:16
df62a91 to
eb6db0e
Compare
karhu
force-pushed
the
tnet-157/21-hints
branch
from
November 10, 2026 14:39
eb6db0e to
c83629d
Compare
karhu
force-pushed
the
tnet-157/21-hints
branch
from
November 10, 2026 15:50
c83629d to
184c7d5
Compare
karhu
force-pushed
the
tnet-157/21-hints
branch
from
November 10, 2026 16:24
184c7d5 to
9f8fb46
Compare
There was a problem hiding this comment.
An organization admin can review the limit in your organization's usage and billing settings.
Once the limit resets or is raised, someone with write access to this repository can comment @claude review on this pull request to trigger a review.
The remedy of an error lived in many places. Some messages carried
it, and the client and timenet-build each had their own hint helpers.
The timenet CLI showed the advice of the SDK, such as "add
InstalledConnectors()". Some hints named a command that fails in that
situation. download(), timenet.build() and timenet.publish() gave no
hint for a missing parent.
An error message now states facts only. TimeNetError has a hint, and
str() puts it after the message. The new module timenet._hints picks the
hint from the facts of the call: the sources, the local registry and the
request. A HintWording gives the parts of the hint that name calls or
commands. A context variable holds the current wording. Its default is
SdkWording, which names SDK calls. Each command of both CLIs sets
CliWording with use_wording(), and CliWording names commands with the
registry flags that the command got. So the client, timenet.build() and
publish() compute each hint once, in the words of the front end. A
command that calls no SDK function, such as timenet local clear, adds
the hint itself. The hint code picks the remedy by the class of the
error, and a subclass without a remedy of its own gets the remedy of its
nearest base class. A lookup that fails with a registry, format or card
error gives no hint. Any other error of the lookup surfaces, so a bug in
it does not hide. A hint names only a call or a command that works. So
it looks at the local registry, the installed connectors and the
registries that the call already has, and at the versions that they
provide. It opens no other registry:
- A release that no source provides names a registry to add. It names
the installed connectors only if a connector builds the release, and a
connector package if none is installed.
- A publish of a release that the local registry lacks names the build
if an installed connector builds the release, else the download. It
asks no registry, so it does not check that a registry holds the
release.
- A damaged copy in the local registry names a download from a registry,
else a forced build, else a registry to add. A failed transfer gets no
hint.
- A download that only a connector can serve, for example of "latest"
when a connector declares a newer version than any registry, names the
build and the exact version that a registry holds.
- A version conflict with the local registry names the copy to delete. A
conflict on publish names a new version. A conflict that
timenet-build build --publish-to finds before the build names --force,
which compares a fresh build with the published release.
- A read or a download of "latest" that cannot reach a registry names
the version in the local registry.
- A stored manifest that is not valid names the folder to delete,
because a download or a build reads that manifest first.
- A provenance record in the local registry that is not valid names the
forced download and the forced build. Both replace the release and its
record. The info and the clear commands of timenet local give this
hint.
- An isolated build that cannot make its environment names
--no-isolation or TIMENET_ISOLATION=off.
- A list or a search whose sources have no catalog names the read of
an exact release: open('<id>@<version>') in the SDK and timenet info
<id>@<version> in the CLI.
Four errors mark some of these situations. TimeNetUnreachableError, a
subclass of TimeNetRegistryError, marks a registry that a request cannot
reach. TimeNetManifestError marks a stored manifest that is not valid,
and its path names the file. TimeNetOriginError marks a provenance
record that is not valid. Both are subclasses of TimeFFormatError.
TimeNetIsolationError, a subclass of TimeNetBuildError, marks an
environment that an isolated build cannot make.
LocalRegistry.release_at() finds the release whose folder holds a path.
TimeNetVersionConflictError gives the location of the destination
registry in registry_location, so a hint can compare it with the local
registry. Its difference is a ReleaseDifference, new in timenet.errors:
FILES or CARD. The difference is now a required argument, and it comes
before needed_by. Manifest.difference_from() compares two manifests of
a release and gives this value. same_release() is gone.
A registry flag that names no registry (--local-registry,
--remote-registry, --publish-to, --dest, --source) is now a usage
error. It exits with code 2 and names the flag. A bad TIMENET_*
variable still exits with code 1 and names the variable.
timenet-build build --publish-to now compares the release in the local
registry with the release in the destination. For another release, it
raises TimeNetVersionConflictError before the build. If the local
registry lacks the release, the version in the destination is enough,
and the command says "Nothing to do". With --force, the command builds
the release again, and the publish compares the files.
The root help of timenet says what the tool does. The help of
timenet-build build no longer shows its Raises section. Every command
has the same help for --local-registry: the local registry, where
downloads and builds land and which a lookup checks first.
BREAKING CHANGE: error messages no longer contain remedies. The remedy
is in error.hint, which str() shows after the message.
Part of TNET-157.
karhu
force-pushed
the
tnet-157/21-hints
branch
from
November 10, 2026 17:41
9f8fb46 to
623c93d
Compare
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.
The Stack
This stack covers refactoring the internal logic of how releases are resolved during read, download & build, in particular also in the context of parent releases / parent datasets. On top of that it refactors the public TimeNet APIs and CLI interfaces around these actions, to streamline the behavior across them.
This PR
Every TimeNet error gets one hint: the call or the command that gets the user out of the situation. The SDK names Python calls, and both CLIs name commands and flags.
Details
TimeNetErrorhas ahint, andstr()puts it after the message.timenet._hintspicks the hint from the facts of the call: the sources, the store, the request and the flags of a command. The client,timenet.build(),plan_build()andpublish()use the SDK wording.timenetandtimenet-builduse the CLI wording.--no-isolationorTIMENET_ISOLATION=off.TimeNetManifestErrorandTimeNetIsolationErrormark the last two situations. They subclassTimeFFormatErrorandTimeNetBuildError.--local-registry,--remote-registry,--publish-to,--dest,--source) is a usage error. It exits with code 2 and names the flag. A badTIMENET_*variable still exits with code 1 and names the variable.timenet-build build --publish-tocompares the release in the store with the release in the destination. For another release, it raisesTimeNetVersionConflictErrorbefore the build. If the store lacks the release and the destination holds the version, the command prints "Nothing to do" and builds nothing. With--force, it builds again, and the publish compares the files.timenetsays what the tool does, andtimenet-build build --helpno longer shows a Raises section.Design decisions
--publish-towithout--forcetrusts a destination that holds the version. A rebuild only to compare costs a full build, so--forcemakes that check explicit.Breaking changes
error.hint, whichstr()shows after the message.timenet-build build --publish-toraisesTimeNetVersionConflictError.Stack
Changes later in the stack:
Merge message