Repository navigation
Description
Question
Editing any existing model input fails at save. This blocks the §8 acceptance criterion for the edit case. Found on #76, walking the signed-in form against TACC's real catalog.
Adding a new input works — variable, standard variable and unit all land in one submission. Editing an existing one does not.
Fault 1 — the save hard-fails (blocker)
The form shows:
expected one of the values ['_PLACEHOLDER'] for type
'modelcatalog_configuration_input_update_column', but found 'is_optional'
InsertConfigurationInputJunction (ui-react/src/graphql/mutations/model-catalog.graphql:406)
upserts the junction row with on_conflict.update_columns: [is_optional]. This repo's own
metadata gives role user only insert / select / delete on
modelcatalog_configuration_input — no update_permissions
(graphql_engine/metadata/tables.yaml:3088). With no updatable column, Hasura generates the
update-column enum with _PLACEHOLDER alone, so the document fails validation.
Not TACC-specific. It comes from the metadata in this repo, so it reproduces on every MINT
deployment, ISI and the dev cluster included.
The sibling mutation already does it right: InsertConfigurationOutputJunction uses
update_columns: [], which is valid with no update permission. The input mutation is the only
one in the file that names a column.
ConfigurationForm.tsx:283 calls insertInputJunction for every row in toUpdate, whether
or not is_optional changed. diffInputRows puts a row in toUpdate on any change, so
editing a label, a format, a description — or the standard variable and unit, which is the SOW
workflow — is enough to fail.
It also half-applies. updateDatasetSpec and updateVarPresentation commit before the
junction upsert throws. I changed one input's format to csv; the save reported an error and
has_format = "csv" was already in the database.
Two candidate fixes:
update_columns: []plus a delete-then-insert whenis_optionalchanged — the pattern the
output path already uses; client-only, no metadata change; or- add
update_permissionsforis_optionaltographql_engine— needs a metadata apply on
every deployment, TACC included.
Fault 2 — a successful save renders stale (minor)
After the successful add, the detail view showed INPUTS (2). The new input was absent until a
manual reload. It was in the database the whole time.
No mutation declares refetchQueries or writes to the cache, and onSaved only calls
setIsEditing(false) (ModelsBrowsePage.tsx:175). The detail view then renders the
GetConfiguration cache entry from page load. A GetConfiguration refetch did go out mid-save
and returned the pre-insert state, so the stale entry is what sticks.
A user configures an input, saves, and it looks as though nothing happened.
Verification
In a real Chrome against https://graphql.mint.tacc.utexas.edu/v1/graphql, signed in as
mosorio@portals via Tapis client mint-localhost-3000. Test rows were written to TACC's
catalog and removed again; the catalog is back to its prior state.
Activity
mosoriob commentedon Aug 9, 2026
Both faults fixed and verified live against TACC. Code in PR #93.
Fault 1 — the blocker
Confirmed under a real Tapis token,
mosorio@portals, and it wrote nothing. Validation runsbefore execution, so sending each document with a bogus id settles it:
on_conflict.update_columns: [is_optional]validation-failed— the exact_PLACEHOLDERerrordelete_by_pk+insert_oneconstraint-violation(foreign key, from my fake id)The new document passes validation and reaches execution. That is the whole claim, measured
rather than argued — and it is a genuine red/green against the user-role schema.
The fix is client-only.
SetConfigurationInputOptionaldoesdelete_..._by_pk+insert_..._onein one document, so both root fields run in a single Hasura transaction andthe row is never left missing. No metadata change, so nothing to apply to TACC's Hasura. It is
now called only when
is_optionalactually changed — the old code fired it for every row intoUpdate, which is why editing a label was enough to fail.Why nothing caught this.
src/graphql/generated/schema.graphqlis the admin schema, socodegen and every offline test validate against a schema where
is_optionalis updatable. Theapp runs as
user, whose schema is narrower. A green build and 760 green tests could not see it.Fault 2 — the stale render
Fixed. The form refetches
GetConfigurationbeforeonSaved;ConfigurationDetailreads thesame cache entry. A failed refresh is swallowed — it must not report a successful save as failed.
End-to-end walkthrough
On
localhost:3000against TACC's live catalog, on configurationsimpleModelAnnotated. I addedmy own throwaway input rather than touch the client's existing
input_file.wf91-probe→ saved. Appeared without a manual reload, heading went toInputs (2). Fault 2 fixed.UpdateConfiguration,UpdateDatasetSpecification,GetConfiguration— no junction mutation, becauseis_optionaldid not change. This is the save that used to hard-fail.SetConfigurationInputOptionalran with no errors; the row readOptionalimmediately, andis_optional: truewas confirmed in the database.simpleModelAnnotatedis back to one input (input_file,unknown, Required) and three parameters: its exact prior state.Not fixed here
The half-apply stays.
updateDatasetSpecandupdateVarPresentationstill commit beforelater steps, so a save that fails midway leaves partial writes. No step in this ticket's path can
fail that way any more, but the save sequence is still many separate mutations rather than one
transaction. Worth its own ticket if TACC hits it; not a blocker for the flip.
fix(ui-react): stop editing an existing model input from failing at s…