Skip to content

August 2026

  • Run a group of steps as one sealed unit — execution containers. On the Advanced workflow canvas, right-click a group and toggle Execution on, and the group runs as a self-contained sub-workflow: it’s redrawn with a distinct border and its own entry and exit ports, and it behaves as a single node in the parent workflow. Nothing inside the group starts until the group’s inputs have arrived, and nothing downstream of it starts until every member has finished — so a whole block of related work fires and completes as a unit, while independent branches inside it still run in parallel. Feed the group by dragging a connector onto its entry port; connect its output by drawing from a member step to the downstream step that needs it, and the runtime seals that through the exit for you. Disabling an execution container skips it as a unit — its members don’t run, and because it produces no output, everything downstream is skipped too rather than running against absent data. See Execution Containers.

  • Run and watch an execution container as a unit. An execution container is now something you start, follow, and recover from on its own. Right-click one and choose Run Group to run just its members, or Run Group + Downstream to run its members and everything downstream — neither re-runs the upstream steps that feed it, so you rerun the group in place rather than rebuilding what came before. While a workflow runs, the container carries a rolled-up status of its members — a status dot, an N of M done count, and a colored border — that reads error if any member failed, running while any is running, and done once all finish; a collapsed group shows the same aggregate as its single tile. When a group has a failed member, click its status to select and center that member, and choose Retry from Failure to re-run only the failed member (or members) and what’s downstream of them inside the group, skipping members that already succeeded — where Run Group re-runs everything. The container header sums its members’ last-run durations, hovering an entry or exit port lists the tables crossing that boundary, and the Run Monitor’s step table now shows each step’s container and that container’s rolled-up status, matching the canvas. See Running and Monitoring Execution Containers.

  • Run an execution container once per iteration — iterate it. Right-click an execution container and choose Iterate…, and the whole sealed group runs once for every value in a set, instead of once. The dialog uses the same iteration model as the Workflow Loop step: define one or more loop variables and the steps inside reference each like any workflow variable ({region}), so a member’s filter, expression, or output name can change with each pass. Choose how the set is built — specify the values yourself (an explicit list, or an integer / upper-alpha / lower-alpha range with optional excluded values, per variable), or take the unique combinations of values in a table by mapping its columns to variable names, with optional row filters. With more than one variable the group runs once per combination. Iterations run one after another — the members share the loop variables — so a container looping region over East, West runs its steps twice, once filtering WHERE region = 'East' and once WHERE region = 'West'. A container is capped at 1,000 iterations. Because each pass overwrites the group’s output tables, a step downstream of the container reads the last iteration’s output; an option to combine all iterations’ output so the passes accumulate is a later capability. See Iterating a Container.

  • Copy and paste steps on the Advanced workflow canvas, links and groups included. Select steps on the canvas — or a whole group, which brings its steps with it — press Ctrl/Cmd+C, and paste them into any workflow, in this project or another, with Ctrl/Cmd+V. The connections among the copied steps come across, the group boxes come across, and the copies land where you point and stay selected so you can drag them into place. A link to a step you didn’t copy is dropped — there is nothing on the other end to attach it to — and the paste tells you when that has happened rather than dropping it silently. It is the same clipboard the steps table uses, so you can copy in one and paste in the other. A large paste runs in batches, showing progress you can cancel, and never caps or silently drops steps; Ctrl/Cmd+Z right after a paste removes what it added. See Copy & Paste steps.

  • You can now re-sync a project against the one you copied it from, so a change made in one project can be promoted forward to another without an export or an archive. When you build a project by copying from another with Copy Project, PlaidCloud remembers which object came from which — so Re-sync Into…, on a project’s actions menu, compares the two by that lineage rather than by name. An object an earlier copy renamed still lines up with its original, and only what genuinely changed shows as a difference; you then merge the pieces you choose, exactly as in an ordinary comparison. This is what lets one tenant hold Dev, QA and Production as separate projects and move changes forward between them. If you re-sync a pair that was never connected by a copy, PlaidCloud says so and falls back to an ordinary comparison rather than pretending. See Re-syncing From the Project You Copied From.

  • A project can now be copied into a project that already exists, not only into a brand-new one. The Duplicate Project action is now Copy Project, and its dialog asks where the copy should go: a new project, as before, or one you pick from the list. Copying into an existing project adds to it — the target keeps its own name, ID, data connection environment, storage defaults, document account, access type, access lists and row-access grants, and only the contents you selected are brought in. Where the copy carries an item the target already has, you choose whether the incoming version replaces it or lands alongside it with copy appended.

    This is for taking part of one project into another — a few workflows and the dimensions they use — without exporting an archive and importing it back. You still do not have to work out what those workflows depend on: anything you tick brings its tables, dimensions, user-defined functions and sub-workflows with it.

    A copy into a project you hold no role on, or one that has been locked to prevent changes, is refused before anything is read or written, and a project cannot be copied into itself. See Copying a Project.

  • A PlaidLink agent can now be assigned to an environment, so switching a project’s environment switches its agents too. A connection already holds a different configuration per environment, so moving a project from your default environment to QA re-points every connection it uses in one action — but the agents that run its remote steps stayed put, and pointing a project at a different machine meant editing every step that named one. Each agent now carries an Agent Group, naming the agents that stand in for each other, and an Environment, saying which one it serves. A step still names a specific agent; the run picks whichever member of that agent’s group serves the project’s current environment. Set the two fields once per agent — there is no per-step change, and no table to keep in step across machines.

    Nothing changes until you set a group. An agent with no group serves every environment exactly as today — which is every agent you have until you change one — so a workspace running a single agent is unaffected. Setting a group makes the match exact for every agent in it: a project running in an environment none of the group serves stops with a message naming the group and the environment, rather than falling back to whichever agent the step happened to name. Running production work on a test machine is the failure this prevents, so add an agent for each environment your projects run in, and leave the group blank on an agent that should keep serving everything.

    The machine has to agree with the record. PlaidLink listens on one queue for the environment named in its own configuration file, so setting an agent’s Environment to QA in PlaidCloud while its machine is still configured for the default environment leaves it listening where no work is sent — the step waits and then reports that the agent is not picking up the job. Set the environment name in the environments block of that machine’s PlaidLink configuration at the same time, and restart the service. See Agent Environments.

  • A new Row Access screen for security groups. Under Identity → Security Group, declare which column on a project governs row access, and grant specific values of it to specific security groups — every project and attribute always shows Granted, Unrestricted, or Denied, so a locked-out group is visible rather than looking unconfigured. The screen records the configuration; applying it to your dashboards is the separate action below. See Managing Row Access.

  • Row Access can now be applied to your dashboards, with a button. What you grant on the Row Access screen was a record with nothing acting on it. Each project on the screen now has an Apply to dashboards button that takes that project’s grants and rewrites its dashboard restrictions to match. It matches rather than adds to: a grant you removed has its restriction removed, and a column you stopped governing has its restrictions taken away — so re-applying after a change is how you publish that change, and applying twice does no more than applying once. Applying a project needs the same access as editing its grants: Architect on that project, with the project unlocked. When you apply, PlaidCloud tells you what it applied and what it deliberately left alone — a column drawing its values from a dimension or a typed list is reported as not yet applied rather than silently dropped, as is a table whose governed columns all let ungranted groups see everything.

    The first apply on a workspace needs a one-time approval, and there is no undo for it. It takes ownership of the dashboard roles PlaidCloud manages, and the dashboard service keeps no history of role membership to roll back to. So the first time you click Apply to dashboards, a confirmation appears describing it as a one-time, permanent, workspace-wide authorization; a workspace administrator confirms it once, and it records whoever is signed in — so it cannot be given on someone else’s behalf. Until it is given, applying a project is refused and nothing is written to your dashboards. (These actions are also available through the API for automation — POST /rest/v1/analyze/rls/reconcile, plus GET /rest/v1/analyze/rls/first-write-diff to preview the first-apply role changes and POST /rest/v1/analyze/rls/first-write-approval to record the approval.) See Applying Row Access to Dashboards.

  • Resume can now pick up from the top of the chain when you resume a nested child workflow. A workflow that ran as a child of another — invoked by a Run Model step in a parent — cannot continue the parent’s orchestration by resuming on its own. Resume now offers Resume from top of chain, which resumes the top-level parent instead and continues the whole chain from where it stopped; resuming a top-level workflow is unchanged. The top of the chain is resolved within the same project — a chain that crosses into another project resumes from the top of the in-project portion. See Run a Workflow.

  • An allocation answer that spots offsetting movement now suggests the more useful next step first. When large rises and falls cancel out, the answer’s opening line tells you the net understates what happened and to narrow to one member — but the suggestions underneath offered only to break the change down by a field. On a real tax model that breakdown returned an answer identical, word for word, to one the same answer had already shown, while narrowing to the member it names gives that member’s own change of +31.2% with every warning cleared. The narrowing step now comes first and names the member; the breakdown is kept below it. Where the movement sits in rows that have no value for the field there is no member to name, so the breakdown stays first and the answer says why. This matters most for an assistant reading the suggestions programmatically, which previously had no route to the better answer at all. No figures change. See Understanding the Answer.

  • The Alteryx conversion matrix now says what its coverage levels are measured against. A coverage level such as Fully Converts is a statement about a tool, not about every one of its configuration options — and the page never said so. It now explains that parity is tracked one configuration path at a time, that each path has to convert, run, and produce the right answer, and that a path we cannot convert correctly is refused by name at conversion time rather than approximated into a quietly wrong answer. It also states how correctness is established without an Alteryx licence in the loop. Nothing about your conversions changes; what changes is that you can tell what the table is and is not promising. See How Coverage Is Measured.

  • Alteryx tools that PlaidCloud does not convert yet now refuse by name. When an imported workflow uses a real, published Alteryx tool that PlaidCloud has no conversion for, the step now stops with a message naming the tool and its Alteryx category — for example that Rank (Preparation) is a recognised Alteryx tool that isn’t converted yet — instead of the generic “unrecognised tool” note that every unknown thing used to get. A genuinely unrecognised plugin, such as a typo, still gets the generic message, so you can tell a tool that simply awaits support from one you should double-check in the source workflow. Marketplace connectors are named this way too, with the guidance to connect through a PlaidCloud connection. See Recognised but Unconverted Tools.

  • Three more Alteryx conversions now refuse by name where they used to answer a different question. Each of these produced a green run with a quietly wrong number; each now stops at conversion time and says why, because a named refusal you can see beats a wrong answer you cannot.

    • Summarize’s First and Last. These take the value from the first or last record in incoming file order. A converted workflow is a set-based query, which carries no reproducible record order — upstream joins, filters and unions do not preserve the order the records arrived at the Summarize tool, and no imposed sort recovers it — so there is nothing to take the first or last of. The conversion used to pick an arbitrary value from each group, which matches Alteryx only when the column happens to be constant within the group. It now refuses, naming that incoming record order is not reproducible, the same reason a position-based Calgary read refuses.

    • The Distance tool’s output unit. Miles, kilometres, metres, feet, yards and nautical miles convert. Any other unit — a drive-time unit, or anything the tool does not recognise — used to fall back to a factor of one, emitting metres in a column named for the unit you asked for (a DistanceYards column holding metres). It now refuses by name rather than answer in the wrong unit.

    • The Action tool. An Action updates a setting on another step from a converted app input. Where the specific update had no conversion, it used to be recorded and then quietly dropped, while the step reported success and the target was left unchanged — and an Action was the one tool that could never be marked unconverted. An update the conversion cannot apply to its target now fails closed and names itself, like every other tool.

    Workflows imported before this release keep the conversion they were given — import them again to pick these up.

  • The dashboard list now respects per-dashboard restrictions set in the dashboard service. A dashboard can be restricted there to particular roles. Where one has been, PlaidCloud now lists it only for people holding one of those roles, along with its owners and dashboard-service administrators — previously the restriction applied when you opened the dashboard but not to the list, so a restricted dashboard stayed visible to everyone who could reach its project. A dashboard with no such restriction is listed exactly as before, to exactly the same people, and no dashboard is restricted this way today, so nothing disappears from your list as a result of this change. One thing to know: your dashboard account has to exist before a restricted dashboard can reach you — until then restricted dashboards stay hidden while unrestricted ones are listed as normal, so open any dashboard once from PlaidCloud and the restricted ones you hold a role for appear. See Which Dashboards You See.

  • An imported Alteryx workflow’s random sampling tools now run. Create Samples — the three-way Estimation / Validation / Holdout split — always draws from a fixed random seed and gives you no way to turn that off, and Random % Sample can be set to one. Both used to arrive as steps that stop with an error, so a workflow built around a sample could not be run at all. Both now run, and every size, percentage and split proportion comes across exactly: each sample holds the share of the records it was configured for.

    The records inside it are not the ones Alteryx picks, and a re-run picks a different set again. Alteryx returns the same records for a given seed on every run, and nothing here reproduces that generator. Each imported step says so on the canvas and in the conversion report, and neither tool is reported as one that failed to convert — so validate these on row counts and proportions rather than on which rows came back. Where which record lands in which sample actually matters, decide it with a column instead: a Formula step that computes the assignment and a Filter step per sample. See Random Sampling.

  • An imported Alteryx workflow now arrives with its comments and containers. The notes an Alteryx author wrote around their work, and the containers they grouped tools into, used to be discarded — so a converted workflow lost every bit of the explanation that came with it. They now come across as canvas objects: a comment box becomes a note, a comment box drawn as an empty outline around a set of tools becomes a highlight box, and a Tool Container becomes a group holding the steps that were inside it, keeping its caption, whether it was folded shut, and whether it was switched off. Nested containers come across as nested groups. Move, edit, recolor, or delete any of them like one you drew yourself.

    As canvas objects rather than steps, they also stop costing anything at run time. Each one used to become a do-nothing step with a warehouse table of its own: across our 178-workflow Alteryx reference set that was 2,413 steps of the 4,759 imported, and 2,409 tables nothing ever wrote to.

    A Control Container keeps its gate. An Alteryx Control Container runs the tools inside it only when the stream wired to its Control input carries records, and that condition now comes across with the group: every step that was inside is imported already set to run only when the gated data has rows, and to be skipped when it does not, nested containers included. Where the tool feeding the Control input produces no data to test against, there is nothing to build the gate from — and rather than importing the interior to run every time with nothing on the canvas saying so, the import now brings the container in as a step flagged for review that says exactly that, and fails when the workflow reaches it. See Control Containers.

    Two things behave differently from the original, both deliberately. A switched-off Tool Container’s tools are still not imported — Alteryx does not run them either — but the container now comes across as a highlight box carrying its caption, so you can see what was there. And box colors are not carried over: the canvas offers a fixed set of six, and Alteryx boxes are almost always white or grey, so every one would arrive the same shade; they come in with the canvas default instead. Workflows imported before this release keep what they were given — import again to bring their comments and containers over. See Migrate Alteryx Workflows.

  • A Browse in an imported Alteryx workflow is now part of the canvas rather than a step. An Alteryx Browse is a viewer: it displays the records reaching it, changes nothing, and has no output connector. In PlaidCloud every step’s output table is already there to open, so what an author drew a Browse for is one click away from the step above it. Each one used to become a do-nothing step that the workflow then discarded — while still claiming a warehouse table of its own that nothing wrote and nothing read: 152 tables across our 179-workflow Alteryx reference set. A Browse was also reported as a tool that failed to convert whenever the tool feeding it failed, so one broken branch appeared twice in the conversion report — once against the tool you actually have to fix, and once against a viewer that could never have run. Fourteen of that reference set’s reported failures were of that kind, and those entries are gone; the tool actually to blame is still reported. How many workflows convert with every tool converted is unchanged — what this removes is misleading entries in those reports, not the failures behind them.

    One shape of workflow now stops where it used to run, and that is the fix rather than a new break. Where a workflow numbers a tool inside a macro the same as a tool on the canvas that calls it, a step below the macro resolved to the Browse’s table name instead of the macro’s own output. That step was never reading the Browse’s records: the table was created at import and then never written by anything — the Browse itself was dropped before the workflow was built — so the step read an empty table and the run reported success having processed no records. With the table no longer created, that step now stops and names it, so a workflow that was already producing figures from no records says so rather than looking like it worked. Re-point that step at the table it was drawn to read. Workflows imported before this release keep the conversion they were given — import them again to pick this up. See The Browse Tool.

  • Alteryx Calgary database tools now convert. An Alteryx Calgary database (a .cydb file) is a proprietary indexed store nothing outside Alteryx can open, so Calgary Loader, Calgary Input, Calgary Cross Count, Calgary Join, and Calgary Cross Count Append used to arrive as steps that stop with one generic note. Each .cydb now stands for one ordinary PlaidCloud table, named calgary_<database name>: a converted Calgary Loader writes that table from its input, and a converted Calgary Input or Calgary Cross Count reads it back, applying the tool’s saved query as the filter or the counted buckets. A workflow that writes and reads its own database converts end to end; a workflow reading a database built elsewhere — the demographic files Alteryx ships, for instance — gets a step that stops and names the table to load before it can run.

    A query built from an Or, or a Not wrapped around a group of conditions, now converts too. Previously any Calgary query that was not a plain list of AND’d comparisons was refused outright. That now converts, covering a record read, a count-only read, Cross Count, and the buckets inside a Cross Count’s custom fields alike.

    A Calgary Join now converts when it matches on an ordinary, non-spatial field. Calgary Join and Calgary Cross Count Append match every incoming record against the database through one of its indexes, and the workflow file records the index’s name but not its kind — the same settings mean an exact-match join against a value index and a “which points fall inside this shape” match against a spatial one, with no way to tell which from the file alone. The incoming field’s own declared type settles it, because a spatial index can only ever have been paired with a spatial field. So a Calgary Join whose incoming field is an ordinary value converts to a match against the stand-in table, keeping the records that matched and carrying its input’s columns through.

    Where the incoming field is spatial, or its type could not be determined, the step still stops — but it now says which, and what to do about it. A spatial field is named as such, with the stand-in table to rebuild the match against as a Spatial Match step; an undetermined type is named as an undetermined type rather than guessed either way. Calgary Cross Count Append stops on every incoming field, spatial or not, because it appends the counts of the matching records rather than the records, and Alteryx does not document how many count columns that produces or what it names them. A Calgary Join also stops when it is set to count matches only, when it matches against a range of index values rather than a single one, when its unmatched-records output is wired to something downstream, when it names no field to match on, and when nothing is wired to its input. A handful of other shapes stop too, each naming itself: contains, starts-with, and spatial-lookup queries; a read limited by Skip Records or Max Records; a Cross Count grouped by more than one custom field, whose column naming Alteryx doesn’t document; a Calgary Loader that stores no data field; and a Calgary tool naming no database at all.

    See Calgary Databases.

  • A converted Cross Tab now carries its percent and total columns. Percent Row, Percent Column, Total Column and Total Row had no equivalent, so a Cross Tab using any of them stopped the conversion and took every step below it with it. All four convert now: the percents as the cell’s share of its row’s or its column’s total of the data field, Total Column as that row total under the name the tool recorded, and Total Row as an extra record of the totals. The percent columns are written on a scale of 0 to 100 — Alteryx documents these methods only as calculating “a percent based on the values” and never says which scale it means, so that reading is inferred from how it renders them. Compare one converted Cross Tab against a run of the original before its figures reach a published report. Two shapes are still flagged for review rather than guessed at: a Total Row on a Cross Tab with no grouping field, and a Total Column whose name the tool never recorded. See Cross Tab Percent and Total Columns.

  • Excel exports are around twice as fast, and no longer grow their memory use with the size of the export. A large export previously held the whole result in memory while it built the file, so the biggest exports were also the ones most likely to run out of room and fail. The file is now built as the data is read, so the memory needed stays flat whatever the row count, and a typical large export finishes in roughly half the time. The resulting workbook is unchanged.

  • An Excel export too large for a worksheet now stops immediately and says why. A worksheet holds at most 1,048,576 rows and 16,384 columns, and a step asking for more used to spend the whole export producing a file Excel then refused to open. It now checks before it starts and names CSV and Parquet as the alternatives. Very large exports that exceed what the file format allows are reported the same way. See Export to Excel.

  • AI agents connected over MCP get leaner results, and are told when a list was cut short. Listing and lookup tools now return the first 25 matches per page rather than 50, and an agent can name the columns it wants with fields=[...] instead of taking the whole record — so a routine “list the tables in this project” costs a fraction of the agent’s limited reading capacity, leaving more room for your actual question. A page that was capped now says so explicitly, so an agent asks for the next page instead of quietly treating the first 25 as the complete answer, and asking for a column that doesn’t exist returns a clear error naming the columns that do, rather than silently leaving it out. Nothing is out of reach: raise limit, or page with the cursor. See Getting Started with AI Coding Agents.

  • A large result now sends each field name once instead of once per row. Where every row of a result carries the same fields, it comes back column-oriented — the field names in one list, the values in another — which is around 30% fewer characters on typical listing traffic and leaves correspondingly more of an agent’s reading capacity for your question. Connected agents are told about the shape and read it without any prompting from you, and no value is changed on the way. Small results, and results whose rows differ, are unchanged. If you read these responses from your own code rather than through an agent, handle both shapes. See Column-Oriented Results.

  • The AI assistant carries a leaner tool catalog. The list of available tools the assistant loads on every turn is about a third smaller, with no loss of capability, so more of its capacity goes to your question. A batch of tool descriptions that told it the wrong thing — naming a tool that doesn’t exist, describing an optional field as required, quoting an error the platform never returns — has also been corrected, so it wastes fewer turns on requests that were never going to work.

  • Cost-tracing can search combinations of dimensions. Where your workspace has explanatory-cut discovery switched on, asking what drove a change in an allocated cost now also tests combinations — a move confined to one region and one product line, say — rather than one dimension at a time. Previously the combination search never ran at all unless it was requested explicitly, which nothing did. The answer stays conservative: where nothing explains the move on its own, it says so rather than picking something. Both searches remain off by default. See Tracing Allocations with an MCP-Connected AI Agent.

  • The step palette in the Visual Workflow Designer is now organized into folders. Every step type used to sit in one long list you scrolled through. Steps are now filed in ten folders that start closed, so you see a short, scannable list instead of the whole catalog — and your favorites stay pinned above the folders, where they were. Filter… still searches everything at once, open or closed, and returns a plain list of matches.

    Clicking a step now adds it. It appears near the top left of the canvas, already selected, ready for you to drag where you want it — and if you picked the wrong one, Delete removes it without hunting for it first. Dragging a step from the palette still drops it exactly where you let go.

    Step names are long, so you can widen the palette by dragging the divider beside it, and it remembers the width for next time. See Advanced Workflows.

  • The step palette is easier to read and can be driven from the keyboard. Folders are now shaded by depth and draw a guide line down everything inside them — click a guide to close that folder without scrolling back to find its heading — and they open and close with the same +/− box the dimension screens use. The heading of the folder you are reading stays pinned to the top of the list as you scroll, opening or closing a folder no longer throws away your place in the list, and Expand all folders and Collapse all folders sit in the palette heading. Clicking a step flashes the row so you can see the add landed, and Filter… now lists each match under the folder it came from rather than flattening everything into one anonymous list.

    The whole palette is keyboard operable and navigable with a screen reader. Tab into the list and the arrow keys move through it, Left and Right close and open folders, Enter adds the step you are on, and Esc returns you to the filter box. Each row reports whether it is a folder, whether that folder is open, and how deep it sits. See The Step Palette.

  • The palette and the Inspector can be collapsed out of the way, and the Inspector can be resized. Click the chevron in the palette heading or the Inspector header, double-click the divider beside either one, or press [ for the palette and ] for the Inspector, and the pane folds down to a narrow rail with its title running down the side. The collapsed Inspector rail keeps showing the name of the step you have selected, so handing the width back to the diagram doesn’t lose track of what you were looking at, and clicking anywhere on the rail opens the pane again. The Inspector can now also be dragged wider or narrower, like the palette.

    Pane widths and collapsed states are remembered per browser and shared across workflows, rather than saved per workflow. Each pane is remembered separately, so a change to one does not disturb the other: the most recent change to a given pane is the setting the next canvas you open will use, and canvas windows you already have open keep their current layout until you close and reopen them. See Collapse and Resize the Palette and Inspector Panes.

  • The Visual Workflow Designer canvas now follows the Dark theme. Working in Dark used to leave the canvas and everything on it — step tiles, connectors, notes, highlights, containers, the minimap, and the palette, Inspector and Data Preview drawer around it — drawn light against an otherwise dark application. They are now drawn for a dark background, with run-status colors and label text chosen to stay legible against it.

    Diagrams you export stay light whichever theme you use. A dark diagram is right on screen and wrong on paper, so Export as PNG and Export as PDF are pinned to the light colors and read cleanly when printed or pasted into a document. See Dark Theme.

  • Dashboards now hold their cached results for an hour instead of five minutes. Because republishing a table now clears its charts’ cached results immediately, the cache no longer has to expire quickly to keep a dashboard current — so the default lifetime has been raised, and you can set it higher still to match how often the data actually changes. Set it in seconds on a database, under Advanced → Performance → Chart cache timeout, or on a single dataset under Settings → Cache timeout. On a table that reloads overnight, an hour or a day means a morning’s dashboard views are served from cache instead of re-querying the warehouse each time — which is where most of a slow dashboard’s time goes.

    You do not need to change anything to get this — the new default applies everywhere. One case is worth checking: if a table is written to by something outside PlaidCloud, nothing tells its dashboards to drop their cache, so the lifetime is all that refreshes them. Those can now be up to an hour behind rather than five minutes, so set a shorter lifetime on those datasets. See Dashboard Caching.

  • Workflow runs are lighter on the platform. A running workflow now asks PlaidCloud for far less of the same information while it works, which frees up capacity in busy workspaces where many workflows run at once.

  • Creating a dashboard user account is now an administrator-only action. Inside the dashboard service, adding or editing a user account directly is now limited to administrators, and the screens for creating and editing pending registrations have been removed. Nothing changes about how people get to a dashboard: your dashboard account is set up for you the first time you open a dashboard from PlaidCloud, and what you can see there follows from your PlaidCloud workspace membership and security groups. Add, change, and remove people in PlaidCloud rather than inside the dashboard service — accounts made directly in the dashboard service are not connected to your workspace membership and are easy to leave behind. See Managing Workspace Members.

  • A cost-trace answer no longer searches every field on the table when the check that limits the search fails. Where you don’t name a field to break a change down by, the assistant searches for the one that best explains it — and before searching, it asks one quick question of the data to rule out fields that hold a single value throughout, or that are divided too finely to be a grouping. Where that question could not be answered, it searched every field on the table instead, lifting both of those limits at exactly the moment something had already gone wrong, and leaving nothing in the answer to say the search had been unbounded. It now says the search was not run — a limit on the search, not a finding about the data — rather than letting silence read as “nothing explains it”. It says so in its own words, because the reason differs from the one you get when the periods compared are simply too large, and so does what you can do about it: there, narrow the periods; here, name the field you want examined, which works whatever the cause. See Tracing Allocations with an MCP-Connected AI Agent.

  • Where the field that best explains a change is the rows with no value for it, the answer now says how often that field is filled in. That the unassigned rows moved is a real finding and is still reported — a cost that has quietly stopped being tagged is worth knowing about. But it means something quite different on a field that is nearly always filled in than on one that is nearly always blank, and nothing in the answer told you which you were looking at. It now reads “the winning cut is cost_centre’s unassigned rows: cost_centre carries a value on 12% of the rows in the periods compared”. Very sparse and very complete fields read as fewer than 1% and more than 99% rather than as 0% or 100% — neither of which can be true in this case, and printing either would mislead in a sentence added to prevent exactly that. The figure costs no extra work: it is measured by the same question that already rules fields in and out.

  • Two Alteryx formula functions now convert to the right answer. An imported workflow that used Round or RandInt used to convert without complaint and then compute the wrong value. In Alteryx, Round(x, multiple) rounds to the nearest multiple of its second argument — Round(157, 10) is 160 — but the conversion rounded to that many decimal places instead, so it agreed with Alteryx only when the multiple happened to be a power of ten: Round(x, 10) and Round(x, 100) matched by luck, while Round(x, 25) did not. It now rounds to the nearest multiple, and rounds a halfway value away from zero the way Alteryx does, on every warehouse. RandInt was worse — it returned 0 on every row rather than a random number; RandInt(n) now returns a random whole number from 0 to n. Re-import a workflow that used either function to pick up the corrected conversion. Separately, the minute and second extractors DateTimeMinutes and DateTimeSeconds now convert as well, rather than arriving as steps you had to rebuild by hand.

  • Spatial conversions that couldn’t be reproduced faithfully now refuse instead of returning a wrong answer. Three imported spatial cases used to convert without complaint and then answer a different question. A Spatial Match set to a relationship other than Within, Contains, or Intersects — Touches, Crosses, Overlaps, or Centroid-In — ran as Intersects and returned a different set of records. A Find Nearest measured in yards or nautical miles was measured in miles instead, under the original unit’s column name, and one with a maximum distance that was not a number dropped the limit and matched past it. Each now refuses by name, so the gap is visible on the step rather than hidden in a green run — rebuild the step with a supported relationship or unit. Separately, six spatial tools with no PlaidCloud equivalent — Centroid, Convex Hull, Line To Polygon, Point To Line, Geocoder, and Redistribute — now say which tool they are and why there is no equivalent, in place of a generic “no direct equivalent” note. See Migrate Spatial Alteryx Workflows.

  • The faithfulness check no longer passes a reworded answer that dropped one of its warnings. When your assistant rewrites a cost-trace answer in its own words, the check confirms it kept the confidence level, kept every warning, and invented no figure. To decide whether a warning was really stated, the check looks for wording belonging to that warning — and ignores that wording where it is only the answer repeating a name from your own model, so a table called “High Street” cannot pass as a warning about anything. It ignored such a name only from five characters up, so a column named after a word one of the warnings looks for was read as the warning being stated: a rewrite that never mentioned it was passed as complete. Wording is now credited wherever it says something the repeated names did not — including where it spans two names printed one after the other, which a per-name test would have missed. Names of any length are handled, and a warning your assistant genuinely stated still counts even where a column shares a word with it. Only the checking of a rewrite is affected — the answers themselves are unchanged. See Answers You Can Trust.

  • A note that applies to two of your value columns is no longer filed under just one of them. On a result carrying several value columns — cost, revenue and margin side by side, say — a note raised by some of them but not all appeared once, opening with a single column’s name. The other columns it also applied to then read as exempt from it. On a real three-column model the note that a split describes the whole pool only applies to both revenue and margin, and appeared as “Column revenue: …” — while the answer itself opens on margin, so someone asking about margin was shown a caveat about margin under another column’s name. Which column it named was not the first one either, but whichever accounted for the largest part of the change, so it moved with the data. Such a note now names every column it applies to: “Columns revenue, margin: …”. A note that applies to every column still appears without any column name, and one that genuinely applies to a single column still names that one. Where the columns each raised the note with figures of their own, the note stays attached to the column whose figures are shown and names the others after it — “Column revenue (also raised by margin): …” — so a number is never presented under a column it did not come from. No figure, confidence grade or warning changes. See Answers You Can Trust.

  • A Table Anti Join no longer turns a text column into numbers. The step now offers only source A columns as output, matching what an anti-join returns — the rows of source A with no match in source B. Before, when a join key existed on both sides it could be picked up from source B, and if source B typed that column as a number the output column came out numeric even though source A held text. Source B still supplies the join keys; it just no longer offers output columns, and any that were set are dropped when you open the step. The step’s help note also now spells out that it is a left-excluding join — for a left join, use Table Outer Join with its Join Type set to Left. See Table Anti Join.

  • A driver what-if no longer answers with a figure several times too large where the result table is built by more than one step. Ask what a change to a driver would do — “what if this cost centre’s floor space doubled?” — and the answer works out how much of the pool moves by re-dividing that pool under the new weights. Where more than one step writes into the same result table, the pool it read was the whole table rather than the part the allocation you asked about had put there, so it re-divided the other steps’ money as well. On a real model that overstated every figure by five and a half times: a change of about $29,000 was reported as $162,000. Nothing in the answer indicated a problem — the tool asks which allocation you mean before answering, so it read as though naming one had scoped the answer, and the check printed alongside confirmed the result balanced, which it does whether or not the pool is the right one. Rather than guess at which rows belong to which step, the answer now names every step writing that table and points you at the tool that explains a change which has already happened, which handles this case properly. Results written by a single step are unaffected, and the check now says plainly that it confirms the split adds up, not that the amount being split is the right one. See Driver What-Ifs.

  • Excel imports no longer alter values brought into a text column. A code held as a number in the spreadsheet — an account or a product id — arrived with .0 on the end, so 600100 came in as 600100.0. Only the rows actually holding a number were affected, so a column mixing numeric codes with lettered ones came in half-changed, which is why it looked like it was hitting some rows and not others. Three smaller versions of the same fault went with it: a very large whole number arrived in scientific notation rather than as its digits, a date lost its time part, and a duration was written in a form that changed shape once it passed a day. All four now read as they did before July’s change to the way spreadsheets are read. Columns imported as a number or a date were not affected. Re-run the import to correct rows already loaded. See Import Excel.

  • A spreadsheet that records its true/false columns as 1 and 0 imports again. Since July’s change to the way spreadsheets are read, importing a file whose flags are held as numbers rather than as TRUE and FALSE stopped the whole import with an error naming the column — not merely the rows concerned, and not only the flag column. Such files import as they did before. See Import Excel.

  • Copying part of a project now brings the dimensions and sub-workflows it needs. When a copy was filtered to a selection, the dependencies traced for each selected object covered its tables and its user-defined function, but not the dimensions its steps load or allocate against, and not any sub-workflow or macro it invokes. A workflow copied on its own arrived without them — the steps were there, the dimension they read was not. Both are now traced, along with any table that was missing from a step’s cached table list but present in its configuration.

  • A cost-trace answer no longer hides a warning raised by an earlier step in the chain it traced. Where a change is explained through several allocations in sequence, one of the earlier steps can warn that its split describes a whole pool rather than any single member — so a large share of the change credited to one factor there is an artefact of the arithmetic, not a finding. That warning was left out of the answer’s Honest limits, the list whose whole purpose is to be the complete set of what not to trust. It appeared only as an indented fragment inside the trace of what was done, where anyone scanning the limits will miss it — while a different warning raised by the very same step was listed normally. On a real chain the answer stated one step’s change as 82% down to a single factor and withheld the note saying that 82% is whole-pool arithmetic, which is worse than showing neither. Such a warning now reaches Honest limits, named for the step it came from and numbered as the trace numbers it, so it cannot be read as a limit on the headline figure itself. It is still listed once where the same warning applies to both the answer’s own step and an earlier one. The advice it carries is now advice you can follow: it used to end by suggesting a filter, which does not reach an earlier step whatever you pass, and it now points at tracing that step’s own table instead — as does the suggested next step. See Honest Answers.

  • Importing a project archive into an existing project no longer renames its variables to a random identifier. A project variable is identified by its name, so when an archive being imported carried a variable the target project already defined — and you chose Create new copy of duplicate items — the incoming one was given a fresh identifier, which meant it arrived as a variable named something like f47ac10b-58cc-4372-a567-0e02b2c3d479. Nothing referenced it, and every {variable} in the imported steps went on resolving to the target project’s own value. Nothing failed and nothing said so; the import simply appeared not to have taken. A variable the target already defines is now left alone, and the import tells you which ones it kept. See Duplicate Items.

  • Objects copied in by that same option no longer arrive sharing a name with what they duplicated. The rest of what an archive carries — workflows, steps, tables, dimensions, data editors, views and user-defined functions — was given a fresh identifier but kept its original name, so you were left with two workflows called Load Data and two dimensions called Period, indistinguishable in every picker, with anything that looks an object up by name picking between them arbitrarily. A copy is now named the way a duplicated workflow already is, with copy appended and a counter if that is taken too. This applies when the incoming object collides with one already in the project; two objects that merely share a name are unaffected. See Duplicate Items.

  • The Import Table Bundle and Export Table Bundle progress windows no longer show <Information Message> above the progress bar. A dialog that has no message to display was falling back to a placeholder meant for development, and the placeholder was being rendered as literal text rather than filtered out. Dialogs with nothing to say now show nothing there.

  • A cost-trace answer no longer calls several fields too close to choose between whenever rises and falls are cancelling out. Where you don’t name a field to break a change down by, the assistant searches for the one that best explains it, measuring each by how much of the change its largest member accounts for. That measurement was capped at 100% before the candidates were compared with one another — so any field whose largest member moved by more than the net change landed on the cap, and two such fields always looked exactly equal however far apart they really were. That is not a rare case: it is precisely what happens when large rises and falls very nearly cancel out, which is the situation the search is most useful in.

    The answer then said no single field stood out and several had scored similarly, and offered each as an equally good next step. On a real insurance model the three fields accounted for 1166%, 586% and 246% of the change — the first explains the move more than four times better than the last — and the reader was asked to choose between them.

    That question is now answered outright: the account field is named, with the movement behind it — one account up $22.1M against another down $20.3M, under a net change of $1.8M — without your having to name a field yourself. Two related faults are fixed with it. The order the candidates were listed in was capped in the same way, so it fell back to the order they happened to be searched in and could put a weaker field first. And a genuine pair of near-equal fields could be joined by any number of further capped fields that were not close at all. Where fields really are close the answer still says so, and still says they scored similarly rather than equally. One consequence worth knowing: where the answer now settles on a field it previously called too close to call, it stops carrying the note that the split describes the whole pool — because it is no longer only describing the whole pool, it is showing you the breakdown. See Tracing Allocations with an MCP-Connected AI Agent.

  • A cost-trace answer that picks its own breakdown field now warns you when large rises and falls are cancelling out. The same question already carried that warning when you named the field yourself. Where the assistant chose the field, the warning was left out, on the reasoning that such an answer mentions the offset in passing anyway. It does mention it — but without a figure, without it reaching the opening line, and without changing the stated confidence. So the identical pool asked about two ways disagreed on whether the churn mattered.

    On a real tax model the opening line read it rose 3.7% for a change made up of one entity up $6.2M against another down $3.6M. Naming the field explicitly opened instead by saying the net barely moved and warning that it hid large offsetting movements. Both now open the same way. Two smaller things move with it: the answer gives the offsetting movement as the reason for its confidence rather than the fact that it chose the field itself — the confidence level is unchanged, only the reason stated for it — and it lists that warning alongside the one about having chosen the field, so such an answer carries both, each with its own suggested next step. An answer whose movement genuinely runs one way is unaffected. See Answers You Can Trust.

  • A cost-trace answer no longer gives two different percentages for the same finding one click apart. Where you don’t name a field to break a change down by, the assistant looks for the one that best explains it and reports how much of the move it accounts for. That figure is the field’s shift in share of the pool — but the breakdown the same answer suggests you run next reports each member’s own change, which is a different measurement. Both were described the same way, as a percentage “of delta”.

    On a real model the opening answer said one programme accounted for 71% of the move, and the follow-up it had just recommended said 98% — same programme, same column, same period. A reader who checked the arithmetic by hand arrived at the second figure and concluded the first had understated the fall by a quarter.

    Each measurement is now named where it appears. A share-shift figure says so in the sentence carrying it, the note explaining the search leads with what was measured instead of mentioning it several clauses later, and the suggested next step tells you outright that it reports a different measurement and to expect a different number for the same member. Neither figure has changed — only what they are called. See Honest Answers.

  • The same two percentages are now told apart where the search finds nothing, too. Where nothing it tried explained the change well enough to report, the answer still names the field that came closest and quotes how much of the change that field’s largest member accounts for — a figure that reads as small, since it fell below the bar. That figure is a shift in share of the pool, and the very next step the same answer suggests, breaking the change down by that same field, reports the member’s own change. The fix above named the measurement wherever the search settled on a field; this note quoted it with nothing said at all.

    On a real bank model the answer said the branch field came closest at 45%, below the bar for a finding, and the breakdown it recommended in the same answer reported 63% for a branch on the same column. One click apart, eighteen points different, both correct. A reader is told the field does not clear the bar, follows the tool’s own advice, and is shown a bigger number — which reads as the tool contradicting itself, or as the first answer having been wrong.

    The note now carries the same sentence as the answers that do settle on a field, and the suggestion repeats it before you run it. Neither figure has changed — only what they are called. See Honest Answers.

  • A driver what-if now works on an allocation that renames its driver column. Ask what a change to a driver would do — “what if this cost centre’s floor space rose by 10%?” — and the answer reslices the pool exactly. Where the allocation step carries its driver value through under a different name, that question used to be impossible to ask: naming the column as the driver table spells it was declined as the wrong column, and the message told you to use the other name instead, which then failed outright with an internal error rather than an answer. Both are fixed, and the two names are now kept apart deliberately. Ask with the driver table’s own column — the name you can see on it, and the one the answer quotes back — while the cost centres and groups the answer reports are named as the result table spells them, because those are the names you filter and read results by. Only a step that renames a driver column was affected; on every other step the two names are the same. Separately, where the warehouse rejects one of the queries a reslice needs, the answer now says which read failed and whether retrying is likely to help, instead of returning an internal error with the failed query in it. See Driver What-Ifs.

  • A cost-trace knock-on estimate now names the tables you asked about, instead of internal storage codes. Asking what a change to one table would do downstream returns an estimate of how much of that change reaches each table below it. That answer was written around long identifiers beginning analyzetable_ rather than the names your project uses — in the sentence estimating the effect, and in the notes explaining which tables could not be measured or are reached by more than one route. Six such places were affected. Unlike the same problem in refusal messages, this one showed for everyone, not only for questions asked by identifier. Each now reads as a table name. Where several tables are listed together they are ordered by name; and where a name genuinely cannot be resolved the identifier is still shown rather than dropped, so the number a sentence gives always matches the tables it goes on to name. See Honest Answers.

  • A cost-trace answer that declines to give you a figure now names the table you asked about, instead of an internal storage code. Some questions cannot be answered safely — the stage’s input has already been filtered by an earlier allocation, the filter you supplied matches no column on the table, or the table’s columns could not be read at all. In each case the answer explains why and tells you what to ask instead. That explanation used to end on the table’s internal storage identifier, a long code beginning analyzetable_ that no analyst would recognise, whenever the question had been asked by identifier rather than by name — which is what the assistant’s own table lookup hands out, so it was the usual case rather than the rare one. Five such explanations were affected, and each now names the table as your project knows it. Where the name genuinely cannot be resolved — the table has since been renamed or removed — the answer names the step that produced it instead; where there is no such step, because the table in question is one the step reads rather than writes, the reference is left out and the sentence still reads normally. This is the path the assistant takes when it is being careful, so it was the last place an unreadable code belonged. See Honest Answers.

  • A cost-trace answer’s opening summary now puts every one of its qualifications in words. Each answer opens with a one-line headline that ends by listing, in a few words each, the things that qualify it — that a figure describes the whole pool, say, or that no single field clearly explained the change. One qualification had no wording of its own, so it appeared as an internal code, offsetting_negatives_ratio, between two that read as ordinary sentences. Where it appeared it was usually the most important of them: it is the one saying that a headline change of half a percent conceals large movements up and down that very nearly cancel out. It now reads as words, both in the headline and in the summary of the trace beneath it. The full explanation was always given lower down, among the answer’s stated limits, so nothing was ever missing from the answer — it was the short summary, the part most likely to be read on its own, that was unreadable. See Honest Answers.

  • A cost-trace answer now describes what moved in words, rather than in the platform’s own names for it. Every answer names the one factor that accounts for most of a change, and that name was printed exactly as the engine records it — so the single most important sentence in an answer read Dominant: T_total, 100%, where T_total is a term that appears nowhere outside the code. It now reads the change in the pool total, and the other four read as the value coming in, the driver total, the shift in this slice’s share of the pool, and the dimension assignment. The number beside the name is labelled too. The sentence now says the factor explains that share of the move — where the figure used to sit after a comma, which reads as a statement about the factor itself: the driver total, 82% was as easily taken for the driver total having fallen to 82%, and nothing in the answer said what the number measured. It reads the driver total explains 82% of the move now. Where two factors tie, the two are now joined with and rather than a comma, which could otherwise be read as a list of four things.

    Two smaller cases go with it. An answer could give its own confidence two different spellings at once — medium (mostly_clean) in the opening summary and medium (mostly clean) two lines below — because the two sentences were built separately; they now share one wording and cannot drift apart again. And where an answer declines to give a whole-pool figure because an earlier allocation already narrowed what this one can see, it explained itself by quoting an internal signal name in quotation marks; it now says what was seen in plain words.

    Only what the answer says changes. The figures, the confidence grades, the warnings, and the structured fields an application reads are all exactly as they were. This is the third pass over the same family of wording — after the qualifications above, and the stage descriptions before them — and it followed an audit of every place an internal name can reach the page rather than waiting for a fourth to be reported. See Honest Answers.

  • Copying steps between projects works again. The workflow steps screen has two versions running side by side — the current one, and the older one you still reach by holding Ctrl (or Cmd) as you open a workflow — and each kept its own separate clipboard. Copying in one and pasting in the other reported There is nothing to paste on the clipboard for steps you had just copied, in the same tab, seconds apart. You would not necessarily know you had crossed between them: which version you get is decided by a preference rather than by anything you click. Both now share one clipboard, so it no longer matters which version either workflow is open in.

    That clipboard is now held in your browser rather than in the page, so it also survives a reload and is shared by every PlaidCloud tab you have open — copy from a project in one tab and paste into a project in another. Switching workspace clears it, and it is never shared between browsers, machines, or people.

    Two smaller things go with it. Paste → Add Linked Steps (Advanced) now declines a paste into a different project and points you at Append or Insert instead: a linked step is a second placement of a step its project owns, so it means nothing outside that project, and it previously looked like it had worked while adding nothing. And Copy Selected with no rows selected now says so, rather than quietly emptying the clipboard of whatever you had copied before. See Copy & Paste steps.

  • Asking a cost-trace question for a breakdown by a field that isn’t on the table now tells you so, instead of answering confidently without one. The answer came back complete, at high confidence, with the breakdown simply missing and nothing saying one had been attempted — and the next step it suggested pointed somewhere else entirely. It was found on a real model where four consecutive questions each came back that way. Naming a field the table being traced doesn’t have is now refused outright, listing the fields it does have, so you can correct the question in one step. Further up the chain the rule is deliberately different: a field added by an allocation only exists downstream of it, so where a field is genuinely absent from an earlier stage the trace groups by the fields that stage does have — telling you which it left out — rather than losing that stage’s breakdown. And where a breakdown is missing for any other reason, including a passing warehouse fault, the answer now says the breakdown you asked for is not in it and offers a retry: the totals are measured and unaffected, it’s the per-member detail that is absent, not wrong. Separately, an answer no longer describes the period field as auto-detected when you named it yourself. See Tracing Allocations.

  • A cost-trace answer that found no clear best way to break a change down now offers each of the close candidates. Where you don’t ask for a breakdown, the assistant looks for the field that best explains the change. Where the leading fields are too close to separate it declines to crown one — picking between them would be a guess — but it then advised naming a field to break the change down by and named none of the ones it had just found, so the advice could not be followed as given. Each tied field is now offered as its own suggestion, the largest single movement first, and the advice says plainly that several scored similarly so that leading with one is not read as choosing it. A field the search judged too weak to count is not offered as one of these, because it was not close to anything — that case is covered separately, in the entry below. Separately, an answer’s suggestions are now ordered so that any you can act on exactly as written come before any that still need you to supply a value. See Honest Answers.

  • A cost-trace answer that searched for a way to break a change down and found none now says so, and offers the closest field it found. Where you don’t ask for a breakdown, the assistant looks for the field that best explains the change. Where nothing it tried explained the change well enough to report, it said nothing at all about having looked — the answer simply advised naming a field to break the change down by, without saying which, and that advice appeared in a part of the answer you could not act on. It now tells you plainly that it searched, that the change reads as a broad move across the whole pool rather than something concentrated in one place, and which field came closest, with the share of the change that field’s largest member accounts for and a note that it fell below the bar for a finding. That field is offered as a suggestion you can run as written. It is offered as the strongest of a weak field rather than as a tie: the search judged it non-explanatory, and saying otherwise would claim more than was found. Confidence in the figures is unchanged, because nothing was chosen — there is no guess in the answer to discount for. See Honest Answers.

  • A cost-trace answer about a table that recombines several allocation branches now counts the whole table, not its biggest branch. Where the two periods you are comparing are not equally filled, the answer says so and quotes how many rows each period holds — often the only measure you are given of how much of the comparison might be missing. On a table built by combining branches, each branch raises that note with its own counts, and the answer kept the one from the branch accounting for most of the change, publishing that branch’s figures as though they described the whole table. On a real four-branch model it reported 110,565 rows against 47,502 for a table that actually held 122,850 against 52,780 — so the note carrying your confidence in the entire answer left out the other three branches. Combining branches stacks their rows, so the branch counts add up to the table’s, and the note is now built from that total. Separately, any note that quotes figures belonging to one branch now opens by naming it, rather than appearing to speak for the whole table. Every figure in the answer itself was correct throughout — it was this note alone that reported a part as the whole. See Answers You Can Trust.

  • Where a result has several value columns, a cost-trace answer now says which column it searched for an explanation. Where you don’t ask for a breakdown, the assistant looks for the field that best explains the change. A result carrying several value columns — cost, revenue and margin side by side, say — is searched one column at a time, while the answer itself leads with the summary column. So where the search found nothing, the answer stated that no field explained the change and that it read as a broad move across the whole pool, without saying which column it had looked at — and it sat among the answer’s stated limits, the part you read to know what not to trust. On a four-column model the search ran against the first column and reported the closest field at around 45% of the change, below the bar for a finding; the column the answer led with had a field accounting for 63%, and asking for that breakdown returned it one call later. The note now names the column it searched and says the finding is about that column’s change, so a “nothing found” result can be read for what it actually covers. Answers on single-column results are unchanged. The figures were always correct, and what the assistant searches is unchanged — this fixes what the answer claimed about them. See Honest Answers.

  • A cost-trace answer no longer tells you a change was partly offset by movements that were not there. Where the pieces of a change move in opposite directions, the answer says so — and where the largest piece is bigger than the change itself, quoting a share of the change reads as broken, so it says it in words instead. It decided which of the two to use by asking whether the largest piece exceeded the change at all, and the pieces are held to the penny: on a change of $9.3 million whose parts came to fourpence more than the total, and on a $1.7 million one, that fourpence was enough. You were told to expect countervailing movements that were not in the data, and a related note claimed a share exceeded 100% when it did not. Both now need the excess to be large enough to mean something, which every genuine case we tested was by a wide margin — the smallest real one exceeded its change by a third. Answers about changes that really are offsetting read exactly as before, and no figure moves either way. See Answers You Can Trust.

  • The opening line of a cost-trace answer about a result with several value columns now always describes the same column. Each answer opens with a one-line summary, and on a result carrying cost, revenue and margin side by side that line describes the summary column — the last one, the derived figure the question is usually about. It did so only some of the time. Asked why programme margin was eroding, with no breakdown requested, it opened “cost fell 10.4%”; asked the same question with a breakdown by programme, it opened “margin fell 19.9%”. Both figures were correct, and both appeared in the per-column list immediately underneath — but the opening line changed its subject between two forms of one question and never said which column it had picked. It was following whichever column the automatic search for an explanation had run against, which is a detail of how the answer was produced rather than anything you asked about. Because that line no longer follows the search, the notes reporting what the search found now name the column it ran on: a note saying a change concentrates in one programme, or in a combination of two fields, says which column that share is a share of. The breakdown beneath the answer is unchanged and still names its own column, and answers about a result with a single value column are unaffected. See Answers You Can Trust.

  • A workspace no longer becomes slow to respond because of requests whose contents never arrived. Where a request reached PlaidCloud announcing itself but its contents did not follow, the platform went on waiting for contents that were never coming — for as long as twenty minutes — even though your browser had given up on that request after twenty seconds. Each one held a slot on the process that serves the whole workspace, so enough of them accumulating made everything slow to respond, and only restarting the workspace cleared them. Such a request is now given up on after fifteen seconds. Nothing you do legitimately takes that long to send, and file uploads, which genuinely are large, are handled separately and are unaffected.

  • Asking an AI assistant to break an allocation change down by a field that is blank everywhere no longer reports the whole change as coming from a single member. Breaking a change down by a field gathers together the rows that share a value — and rows with no value gather together too, so a field left blank on every row produced one group holding the entire change. The assistant then described that as perfectly concentrated in one member, at full confidence, with nothing to suggest otherwise. It was found on a real model where the field was blank on all 2.4 million rows in the period being compared. The assistant now tells you the field is not filled in for those rows, withholds the concentration figures rather than reporting them as 100%, and suggests either a field that is populated or dropping the breakdown altogether so it can find the field that best explains the change itself. Where a second grouping field is populated, the breakdown is genuine and is kept exactly as it was, with the blank field simply noted. A blank value also now reads as (no value) or (blank) rather than the word None, and the two are kept apart because they are genuinely different. The headline change, its totals and how it was attributed were always correct and are unchanged — only the breakdown was wrong. See Tracing Allocations.

  • Asking what a change to one table would do downstream no longer answers with a figure it could not work out. Where the calculation for one step failed, the result that step writes was reported as receiving the whole change — a maximum, presented exactly like a measured answer, with nothing to tell the two apart. Everything below that step was then estimated from it, so a whole branch of the answer read as ordinary measured estimates. That result now carries no figure at all, the answer says which steps could not be measured and why, and the totals cover only the results that were measured. Nothing downstream of an unmeasured step is estimated from it, and the answer tells you those results are missing rather than leaving you to notice. A result measured from only part of what writes it now says so too, and names the step that could not be read — the figure is a real measurement of what could be read, so it stands, but it is not the whole result and should not be read as a floor. A failure that could previously end the whole request with an error is now reported this way instead. See Tracing Allocations.

  • A workflow step saved with an output column that has no data type now runs. Adding an output column by hand used to leave it without a type. A new row now starts as Text so the step saves (below), but a step already saved that way still failed when it ran — it could not build its output table. The type is now worked out as the step starts, from the source column that output column reads. Where there is nothing to read it from the column is treated as text: an Extract SQL step’s columns come from the query you wrote rather than from a mapped source, and where several sources carry that column name under types that disagree, text is used rather than guessing one of them, since a wrong guess produces a conversion the warehouse can reject. This reaches every step that builds its output table from configured columns — Table Lookup, all four Joins, both Unions, the Extracts, Append, Upsert, the two geospatial steps and the file imports. Multi-Table Join is the deliberate exception: it stops and names the column instead, which is more useful than a guess in a step joining several tables. Setting the column’s Type in the step form remains how you say what the column should actually be; it is no longer the only way to make the step run. See Column Data Type.

  • Creating a table with a column left without a data type no longer fails outright. The column is created as text. This covers tables built through the API and through the AI assistant, where a column can be sent with no type at all rather than with a type you chose. It is a separate fix from the step behaviour above and does not depend on it.

  • A step whose row condition compares a column with no data type now runs. Steps that delete, update or reshape rows in place send their row condition to the engine separately from the rest of the step, and a recent security change to how that condition is read turned away any comparison involving something the platform had no type for — a column whose type was never set, a piece of hand-written SQL used as a column, or the result of a user-defined function. It applied to every comparison those can appear in, not only a check for empty. The step stopped with an internal error about a refused query, which named nothing you could act on; switching the step off and resuming the workflow was the only way past it.

    Separately, a column given the interval type was refused in the same way with nothing untyped in the condition at all, so no row condition on such a column could run. All of these run again. Setting the column’s Type in the step form is still worth doing, but it is no longer what stands between the step and running. Conditions that ran before are unaffected, and the query forms the security change exists to refuse are still refused.

  • A Macro Concurrent step no longer waits forever on a child invocation that has stopped responding. A child reports its own result when it finishes, so a child whose machine stopped without warning never reported anything — and the step went on waiting for it. There was no error and no progress to see: one run sat at Completed 0 of 29 loops for eighteen minutes, with nothing to do but stop it by hand. The step now checks that each child it is waiting on is still alive, and gives up on one that is not — stopping it, cleaning up after it, and failing at the end naming that invocation, the last state it reported, and when it last reported it. The other children are unaffected: they finish and their output tables are written as normal, so one unresponsive invocation out of twenty-nine no longer discards the other twenty-eight. A child working through a single long-running step is left alone for as long as it takes, and a check that cannot be answered — while the platform is briefly unreachable, for instance — is not treated as an answer. See When a Child Invocation Stops Responding.

  • An ML: Train Model step can now save a large model. A random forest left at its default hundred trees could not be saved at all: training itself succeeded, and the step then spent close to four minutes writing the model away before the connection to the warehouse dropped, reporting Broken pipe or Lost connection — which says nothing about what went wrong and does not tell you the training had worked. A decision tree over the same data saved without trouble, so what mattered was the size of the model, not the algorithm you chose. Models are now compressed before they are stored, and a model too large for a single value is split across as many rows as it needs, so the sizes that used to fail now save normally. A model still too large — more than 128 MB compressed, around twice what a default hundred-tree forest produces — now stops as soon as training finishes and tells you its size and the limit, instead of running for minutes and failing with a connection error.

    Two things to know if you read a model table directly rather than passing it to an ML: Score step. It may now hold more than one row, so read metrics_json from a single row — WHERE chunk_index = 0 — rather than assuming there is only one. And the stored model is compressed, so reassembling it yourself means joining the pieces in chunk_index order and decompressing before you unpickle. ML: Score handles all of this, and stops with an error if any piece of the model is missing rather than scoring with an incomplete one. Models trained before this release are still read as they were. See How the Model Is Stored.

  • A report text block now prints the value of a column its text names, instead of printing the reference itself. Text that referred to a column — the attribution line under a converted Alteryx map, for example — was written into the report with the reference still in it, so the finished PDF read [Year:A] © Mapbox where it should have read 2026 © Mapbox. The step reported success and the document looked normal, so there was nothing to notice until someone read the page. Naming a column that the text cannot read now stops the step and says which column, rather than printing the reference onto the page. Ordinary bracketed prose is untouched: a time like [12:30] and an aside like [Note: continued] still print as written. Re-run a report to correct it. See Report Text.

  • A shaded map’s legend now prints the band names the map defines. A converted Alteryx Report Map carries its own band names — High, Above Average, Average, Below Average, Low on a typical map — and the legend ignored them, labelling each band with the range of values it covered instead, down to a band shown as 22322 - 22322. The names are now used. Where they cannot be matched to the bands actually drawn — the shaded values do not reach every band, only some bands are named, or more than one layer is shaded — the step stops and says so, rather than printing a legend that reads correctly while naming the wrong bands. A map that names no bands still labels them by range, so existing maps are unchanged. See Report Map.

  • A date column in an Excel export shows as a date again, rather than as a number like 44355. Date columns were written without their date formatting, so Excel displayed the underlying number instead. Columns holding both a date and a time were not affected. Re-run the export to correct an existing file.

  • Re-importing an Alteryx workflow no longer overwrites the first import’s results. Every import names its tables after the workflow, so two imports of the same workflow — what happens whenever a first import needs correcting — asked for the same names. The second import created its own tables and then went on using the first import’s, so the two shared one set: each run replaced the other’s output, and a run that failed partway left the earlier import’s finished results empty. Both runs reported success. An import that asks for a name the project already holds now uses the table it actually created, named with a -duplicate- suffix, so each import keeps its own data. The same applies to two workflow files whose names match, and to importing into a project that already holds a table of that name. Imports you already ran are not repaired — re-import those workflows to separate them. See Migrate Alteryx Workflows.

  • Converted Alteryx workflows no longer write over each other’s tables. Each converted step writes a table named after the Alteryx tool it came from — tool_4_out for Tool 4 — and Alteryx numbers tools per file, so those names repeat across workflows. A PlaidCloud project is a single table namespace, so importing a folder of Alteryx workflows into one project, which is the usual way to migrate, had each import claiming names an earlier one was already using. Across a 178-workflow reference set, 361 table names were claimed by more than one workflow.

    Steps find their tables by name, so two imports ended up sharing one. That showed up two ways. A step whose columns were not in the table it landed on stopped the workflow with an error naming a column the table does not have. Where the two happened to be compatible, nothing errored and one workflow simply overwrote the other’s results, with both runs reporting success.

    Every import now prefixes its tables with the workflow’s own name, so tool_4_out becomes 03_measure_the_quality_of_data_tool_4_out and two imports cannot collide. Set your own table name prefix during import to override it, or an empty one to get the bare names back. Tables from imports you already ran are not renamed — re-import those workflows to separate them. One case still needs your attention: two files with the same name, names differing only in punctuation or spacing, or a file carrying no name at all all produce the same prefix, so set one yourself for those. See Migrate Alteryx Workflows.

  • A converted Alteryx Batch macro now receives every column the workflow sends it. A macro records the columns it expects to be given, and the conversion built the inside of the macro from only the columns its own steps mention by name — so a column the macro simply carries from its input through to its output was dropped before anything ran, and the columns that did survive were all treated as text whatever type the macro recorded for them. The macro ran to the end either way. A step that needed the dropped column stopped the workflow with an error naming a column nothing had produced. A step that did not need it finished normally and reported success, having worked out its answer from an input that was missing a column — nothing to notice unless you compared the numbers. Numbers and dates arriving as text is the same problem in a quieter form: comparisons and sorting behave differently without anything failing. Macros that repeat until they converge were never affected. Workflows you already imported keep the conversion they were given — re-import those to correct them.

  • A converted Alteryx analytic app’s drop-down and list controls now offer their choices. An analytic app’s Drop Down and List Box questions become PlaidCloud workflow variables with a controlled picker — but the list of options each one offered, and the default it started on, were dropped, so the picker arrived empty and reset to nothing. The options live in the app’s own definition as a plain list, and a default written there as text rather than as an attribute was read as blank. Both now come across: a converted drop-down or list presents exactly the choices the app author set, with the option they chose already selected. A control whose options are drawn from a data source at run time rather than from a fixed list is left to draw them at run time as before. Re-import an app to pick this up. See Validate Analytic Apps.

  • A converted Alteryx Location Optimizer macro now stops instead of running its search once and reporting an answer. Such a macro is only the scoring pass of a search: the search that drives it — generating candidate location sets, how many locations to place, the generation limits and the seed — lives in the calling tool and in the Alteryx engine rather than in the workflow file. The conversion did not recognise it as anything special, so it was treated as an ordinary macro and its interior ran exactly once. The run finished green and produced figures that read as an optimised result while being a single scored guess, with nothing to say otherwise. The macro call now arrives as a step flagged for review, naming the macro, the input its candidate sets arrive on, the output that ranks them, whether a high or a low score wins, and that there is no equivalent for the optimisation loop yet.

    Re-importing a workflow like this will show a refusal where it used to appear to work. That is the fix rather than a feature being taken away — the figures the earlier conversion produced were wrong, and no note said so. See Macros in a Converted Workflow.

  • A converted Alteryx macro called from inside a Batch or Iterative macro now converts. A looping macro whose interior called another macro could not resolve that inner call, and the entire loop conversion was discarded — the call arrived as a placeholder step whose note blamed the loop rather than naming the macro inside it. Interior macro calls now resolve, so those workflows convert. This only ever showed itself on real imports, which is why it went unnoticed. Two arrangements are refused by name rather than converted: a looping macro nested inside another looping macro, and a looping macro that ends up calling itself. Re-import any workflow that landed a looping macro as a placeholder.

  • A converted Alteryx report now finds the images it refers to. An image a report layout named by a fixed path was recorded in the step but never packaged with the workflow, so the converted report still pointed at a file on the Alteryx machine and failed on a missing asset. Those images are now carried across with the workflow. An image whose bytes are embedded in the workflow, or whose path is taken from a column per record, has no separate file to fetch and was never affected. See Reports in a Converted Workflow.

  • A table whose column information could not be read no longer looks like a table with no columns. When PlaidCloud could not read the columns of a table, steps treated the answer as “this table has none” and said so — pointing you at your own step order, and at whether an upstream step had populated the table, when the real problem was a read that failed. Those steps now say the column information could not be read, and why, so the message names the thing to investigate.

    This covers converted Alteryx steps and ordinary Union steps alike. A Union over a genuinely empty source is unchanged; only a failed read behaves differently.

    Two report cases were affected quietly, and both are worth checking. A report snippet whose source could not be read was skipped, and a report table section came out empty — both on runs that reported success, so the report simply arrived with a piece missing. A report that used to come out missing a section may now stop with an explanation instead. See Reports in a Converted Workflow.

  • A converted Alteryx Pie Wedge Trade Area macro no longer breaks the Join below it. The packaged macro passed its input columns through instead of declaring the columns it actually writes, so a Join keyed on the macro’s own key column refused to convert — the column it joined on appeared not to exist. The macro now declares what it writes, and those Joins build.

  • A member you disabled can be enabled again. Disabling a member from Identity → Members recorded the time in a format the rest of the platform could not read back, and the only screen that can re-enable someone reads it first — so the Enable action failed with an internal error, and there was no way to reverse a disable. The same unreadable value also broke the member list itself: with one member disabled this way, Identity → Members and the member pickers that use it stopped loading for everyone in the workspace.

    Both work again, and members already disabled this way can be enabled normally — nothing needs to be re-done to them, and no data was lost. Disabled members remained disabled throughout; what was broken was reversing it and listing them.

  • A converted Alteryx DateTime Now step now writes the weekday and month by name. Its default output format asks for both by name, and both came out as the bare letters A and B — a report reading A, 04 B, 2026 where it should read Tuesday, 04 August, 2026. The step reported success and produced a document of an entirely plausible size, so nothing pointed at it until someone read the output. A time-only format was wrong in a quieter way: HH:mm:ss printed the month name where the minutes belong, rendering 14:22:31 as 14:August:31. Both are fixed, and the single-digit hour tokens h and H now render as hours rather than being left in place. Re-run any workflow whose converted DateTime Now step feeds a report or a saved table; already-written values are not corrected retroactively. See DateTime Now.

  • An Access import that cannot read a table now fails and says which one. Importing a Microsoft Access .mdb or .accdb file whose tables could not be read finished green, leaving a table with no columns and no rows behind it. Nothing surfaced until a later step tried to read that table and failed — reporting an error against that step, which pointed the investigation at the wrong place entirely. The import now fails at the import, naming the file and the table it could not read, so the message names the file you need to fix. A file whose tables are genuinely empty still imports, and reports that it loaded no records. See Import Access.

  • AI agents can now build the text, document, spatial and report steps from their documented shape. Asked to create a Text Sentiment, Topic Model, Word Cloud, PDF text, image OCR, Fuzzy Match, XML or JSON parse, any of the spatial or geospatial steps, or any of the report pieces, an agent read the platform’s own description of the step and built it exactly as described — and the step then failed on its first run, every time, because the description named the input-column list differently from the way the step reads it. Thirty-six step types were affected. The description now matches, so a step built from it runs. Steps converted from Alteryx were never affected; they were already built the right way.

  • The Text Sentiment step’s sentence-level scoring is documented. Find sentiment at sentence level — which scores each sentence in a record and returns the average, rather than scoring the whole body at once — has worked all along, but nothing described it, so there was no way to know it was available or what it changed. It is documented now, including the case that makes it look like it does nothing: on records holding a single sentence, the average over sentences is the whole-body score, so the two settings agree. See Text Sentiment.

  • The dimension-member picker now opens reliably and applies to the right rows. Double-clicking a property cell configured to pick a member from a dimension — in the dimension hierarchy grid or a Data Editor grid — needed a second double-click to open when the cell already had a value, and that second click could land the pick on the wrong row further down the grid. Picking a member in an empty cell and clicking Apply silently discarded it (clicking back into the grid instead of pressing Apply happened to work, which is why it went unnoticed), and in some cases Apply cleared the value instead of setting it. In a Data Editor grid, a pick from the picker was discarded outright. All of these are fixed: the picker opens on the first double-click, and Apply and Clear both work reliably on the row you actually edited, in both grids. When several rows are selected, Apply still applies the value to every selected row — that’s intentional multi-row editing, and it now always includes the row you double-clicked. Separately, a property’s Allow Multiple Selections checkbox, in its Dimension Configuration, can now be turned off; it previously reverted to checked no matter what you saved. See Dimension-Type Properties and the Member Picker.

  • Timestamp columns no longer import as empty on Lakehouse v2. Importing a CSV or other delimited text file into a Lakehouse v2 workspace left every timestamp column empty, while the import itself reported success — so nothing pointed at the problem until a later step or a dashboard turned up missing dates. The date format PlaidCloud handed the warehouse was written in the wrong dialect’s format codes, and the two dialects disagree on the most common one in a timestamp: the code PlaidCloud sent for minutes means full month name to Lakehouse v2. Asked to read 22 as a month name, the warehouse matched nothing and returned an empty value for every row rather than reporting an error.

    The same misreading applied to to_timestamp, to_date and to_char anywhere they appear — a transform expression, a view, or a converted Alteryx workflow — where instead of emptying a column it produced visibly wrong text: a HH24:MI:SS format rendered 14:22:31 as 14:August:31.

    This affected any workspace on Lakehouse v2, not only converted Alteryx workflows. Parquet imports were never affected, because they carry their own column types and never build a date format. No other warehouse type was affected. Already-imported rows are not corrected retroactively — check any table you loaded from text files with dates or timestamps, and re-run those imports.

    If you imported a file after this fix was announced and still found empty timestamps, that is why. The correction reached the main service but not the separate, slimmer service that builds most file imports, which was running an older version of the shared code — so an import that ran there behaved exactly as it had before. Both now carry the fix. Re-run any import you ran between the two and check its timestamp columns.

    One related case is not fixed by this: a column whose data type is Time still imports as empty on Lakehouse v2, for a different reason — the warehouse function used to parse it cannot produce a bare time-of-day value at all. Import the column as Timestamp or as Text until that is addressed. See Import CSV.

  • Adding an output column to a Table Lookup or Join step saves again. A column you added by hand started with no data type, and saving the step failed with Update Failed – Internal Server Error — removing the column again was the only way to save. New rows now start as Text, and you can change the type as usual. The same fix covers the Inner, Outer, Anti and Cross Join steps. A step you already saved with a column that has no type runs as well — see the entry above — though setting the column’s Type is still how you say what it should be. See Column Data Type.

  • Exporting a project no longer freezes the export window, and you can carry on working while it runs. Choosing Export Project Archive used to hold the window on a loading spinner for the whole archive, with no progress shown and no way to cancel or step away — and it gave up with an error after ten minutes even though the archive usually carried on running, so the error told you nothing about whether one had been produced. Ten minutes is well inside how long a real archive takes: on the workspace this was reported from, archives of 42, 45, 54 and 64 minutes all occurred, against 15 seconds to 7 minutes for a typical one on the same workspace — so a large archive failed on screen every time, purely because of how long it took. The window now closes as soon as the request is accepted, a progress window follows the archive, and a notification reports the result — that it finished, which tables’ data was left out, or why it failed. Scheduled archives are unchanged. See Archive a Project.

  • Exporting a project no longer hides a table whose data could not be read, and a failed export says so. If a table listed in the project has no data behind it, the archive is still written — that table’s data is left out and the export finishes with a message naming the tables it skipped. The archive records them, and restoring it names them again rather than presenting them as complete. Separately, an export that genuinely failed used to report as finished with no file behind it, so the problem surfaced later, usually when someone came to restore the archive; a failure is now reported as a failure. This covers every export type, not only project archives. The export window also names the project it is archiving. See Archive a Project.

  • The AI assistant always draws a diagram as a picture, and won’t invent the numbers in it. A requested diagram occasionally arrived as a block of diagram source code instead of an image; it now renders whichever notation the assistant picks. And a chart or Sankey needs a figure for every bar or band — where the assistant hasn’t been given one, it now asks you for it rather than drawing a plausible-looking value, so a picture that reads as authoritative is not quietly made up. See Using the AI Assistant.

  • The AI assistant can send email and SMS again. Asking it to send a message either failed outright or reported success while sending nothing, so there was no way to make it work. Sending now works, and leaving the recipient out is reported as an error instead of quietly doing nothing. See Using Email.

  • Naming a period column the table doesn’t have now fails clearly. Asking cost-tracing to compare periods using a column that isn’t on the table now says so immediately, naming the column and listing the ones the table does have, so you can correct it in one step. Previously the analysis went ahead and came back reporting only that it couldn’t total the figures — which read as a passing glitch worth retrying, when retrying could never help. Driver what-ifs are checked the same way. For a trace or a driver what-if you can still leave the period column unset and have it detected for you. See Tracing Allocations with an MCP-Connected AI Agent.

  • An AI agent watching a list for changes no longer misses an edit. Agents can ask “has this changed since I last looked?” and get a cheap “not modified” when nothing has. That check was comparing only the identifiers in the list, so renaming or editing a record — without adding or removing one — still came back as “not modified”, and an agent could go on working from a stale copy. It now compares the records themselves. A related fix keeps that answer consistent no matter which server handled the request.

  • A cost-trace answer no longer claims high confidence over a chain it could only partly explain. Tracing a change back through an allocation model can reach stages it cannot pin down — most often a table written by two enabled allocation steps at once, where crediting the change to either would be a guess. Those stages were already listed among the answer’s stated limits, but the headline confidence was taken from the final stage alone, so a four-stage trace with two unexplained stages in the middle still read as “high — clean attribution”. Confidence is now held no higher than medium whenever part of the chain went unattributed, and the answer says how many stages that was and why. The figures themselves are unchanged and still reconcile exactly — it is the claim made about them that was too strong. See Honest Answers.

  • A cost-trace answer’s list of top movers now describes the table you asked about. Where a change was traced back through more than one allocation stage, the member breakdown printed beneath the headline came from the deepest stage the trace reached rather than the table the question named — so a headline about one table, narrowed to one country, was followed by a list of members belonging to a different table, across every country. Both sets of figures were correct in themselves, which is what made this so easy to miss: nothing failed, nothing was flagged, and only the pairing of the two was wrong. In the case that prompted this, a headline reporting a fall of $9.3 million was followed by movers adding up to $16.2 million. The breakdown now always describes the table in the headline, at the same scope, and adds up to the headline figure. Two related cases are fixed by the same change: where the deepest stage was one the trace could not attribute, and where the chain passed through a recombined result on its way back, the breakdown simply disappeared with nothing said about it. A trace through a single allocation stage — the common case — was never affected, and neither were the headline, the totals, or how the change was attributed. See Tracing Allocations.

  • A cost-trace answer about a table that combines several allocations now describes every one of them. Where each of those allocations moves more than one value column — cost, revenue and margin together, say — the answer named only the first allocation and presented its columns as though they were the whole picture, leaving the others out entirely. The opening line meanwhile counted every column as a separate branch, so a table combining two such allocations was announced as six. Every figure shown was correct, which is why nothing flagged it: what was wrong was which allocations the answer claimed to cover, and the two halves of the same answer disagreed about how many there were. Branches are now counted as branches, each line names the value column it describes where an allocation moves several, and a branch whose own columns move in different directions is reported as having moved both ways rather than being assigned one. Answers about a table combining single-column allocations, and about a single allocation moving several columns, are unchanged. See Tracing Allocations.

  • A cost-trace answer that leaves out the step-by-step chain no longer loses the note saying its list of movers was cut short. An assistant can ask for a shorter answer that omits the chain of steps behind it. The list of top movers survived that trimming but the note saying it showed only the largest few did not, so a ranked list of five out of twelve members read as though it were complete — and the same applied to the note saying a breakdown had collapsed into a single group. Both notes now travel with the list they describe rather than with the chain, so asking for a shorter answer no longer changes what it claims.

  • A cost-trace answer about a total that crossed zero no longer contradicts itself. Where a total moved from positive to negative between the two periods, the change cannot be divided between the things that drove it — that is two states, not one movement to apportion — and the answer has always declined to try. But its opening line gave the wrong reason: instead of naming the sign change, it repeated a general note about how the measurement is taken, which read as the explanation and disagreed with the line printed immediately beneath it, which had it right. It now names the sign change and says what to do instead. The percentage is also no longer shown for such a change: a swing from a small positive to a large negative produced a figure like -10013.2%, which measures nothing, and the answer carried a second, differently-calculated percentage alongside it. The amounts either side, and the change itself, were exact throughout and are unchanged. See Tracing Allocations.

  • A cost-trace answer now suggests a next step where the trace stops, and stops suggesting one you have already taken. Every answer ends with next steps you can run, and the two situations that offered none were the two where you were most stuck: a total that crossed zero, and a stage that could not be aggregated at all. Both now carry a suggestion — the second naming the table to check and the likeliest cause, a period column missing from that stage’s table, so it can be ruled out before a passing warehouse fault is assumed. Separately, an answer scoped to a single member no longer advises you to scope it to a single member: that advice came from a limitation recorded further up the chain rather than from the question asked. (The limitation itself is stated — see the entry above; it is the advice that was stale, and it now names what you can actually do about it.) One case still offers no next step — where an independent read of the driver table disagrees with the realised split, the useful move is to inspect that driver table directly, which is a separate request rather than an adjustment to this one. See Tracing Allocations.

  • Searching warehouses by name returns the matching warehouses. A name search answered with a bare identifier instead of the matching records, so an agent got neither the details nor a count, and an empty result was indistinguishable from an error. It now returns records like every other search, and matches on any part of the name regardless of case.

  • Republishing a table now clears the cached results of the dashboards reading it. A dashboard caches each chart’s results so repeat views don’t re-query the warehouse. Those cached results were meant to be discarded the moment a workflow run republished the underlying table — but the discard never took effect, so a chart could keep serving pre-refresh numbers until its cached result expired on its own. Republishing now clears them straight away, and the next person to open the dashboard sees the new data without forcing a refresh. See Dashboard Caching.

  • Signing in to dashboards no longer loops for a member who has a duplicate dashboard account. For a small number of people, opening a dashboard landed on the dashboard sign-in page and left it flickering — repainting roughly once a second — without ever reaching the dashboard. Those members had ended up with two dashboard accounts whose email addresses differed only in capitalization, such as Jordan.Smith@example.com and jordan.smith@example.com. Sign-in matched both, could not tell which one was meant, and so treated the person as somebody signing in for the first time; creating the account then collided with the one already there, and the attempt started over from the sign-in page. Sign-in now settles on a single account instead of giving up — an account that is still active, then the one whose capitalization matches exactly, then the oldest — so those members sign in normally. Two dashboard accounts differing only in capitalization can also no longer be created in the first place. This only ever affected members who had a duplicate account of this kind; everyone else signed in normally throughout. If someone reported a flickering or looping dashboard sign-in page, this release fixes it, with nothing for you to clean up.

  • A step whose run was interrupted now reports itself as abandoned, instead of appearing to run forever. When the work behind a step went away mid-run — because someone pressed Stop, or because platform maintenance interrupted it — nothing ever corrected the step’s status. The workflow view kept showing it as running with a duration climbing indefinitely, which reads as an extremely slow step: in the case that prompted this, a step that takes three seconds displayed as running for over twenty minutes.

    Such a step is now marked abandoned, with an explanation in its status tooltip, and its duration stops. An open workflow view refreshes on its own, so it corrects itself without a manual reload. An abandoned step did not complete and produced no output — it is not a slow step and not a data problem. You can either Resume the run, which runs the abandoned step again, or re-run the whole workflow. See Follow a Step’s Status.

  • Resume picks a workflow back up where it stopped, including inside called workflows. A run that failed several levels deep — a workflow calling a workflow, or a loop step working through its iterations — restarted the first called workflow from its opening step instead of returning to the point of failure, repeating everything in between. Resume now returns to the step that failed, at whatever depth it sits, and a loop step resumes the interrupted iteration and skips the iterations that already completed. See Run a Workflow.

  • Resume no longer re-runs completed steps on parallel and Advanced workflows. On both, Resume restarted the whole workflow, so every step that had already succeeded ran a second time — including any sub-workflows they called. Both now re-run only the step or node that failed and whatever was still waiting on it. If you had been using Resume on a parallel workflow as a way to re-run everything, use Run All instead. See Run a Workflow.

  • Resume reliably continues the original run, whatever you did in between. Resume re-runs everything the run still had left to do — every step that is not sitting in a finished, successful state — instead of picking up from a position an action taken since had moved. Re-running a single step on its own no longer changes where Resume goes next; it still continues the run it belongs to. And a step that failed is re-run on Resume, rather than being mistaken for one that finished. See Run a Workflow.

  • Resuming a Run Selected run keeps its selection. Resuming a run that had been scoped to a chosen set of nodes on the Advanced canvas widened it to the whole workflow. The original selection is now preserved. See Advanced Workflows.

  • Saving a security form with nothing selected now tells you nothing changed. Assigning members to a group, or groups to a member, and saving with an empty list reported success while making no change — and on the member form it could instead remove every group that member had. An empty list now leaves the assignment alone and says so. See Managing Security Groups and Assignments.

  • Re-creating a workspace member no longer resets their reports and dashboards access. Removing a member has never deleted their account in the dashboard service, so removing someone and later adding them back — a rehire, a corrected email address, undoing a mistaken removal — used to reset that leftover account to the most basic access level, silently discarding administrator access, elevated report-building roles, and any role controlling which rows a report shows them. Re-creating a member now leaves their existing access untouched; a genuinely new member still starts at the standard level. If someone was removed and re-added before this fix, their previous access was not recorded and must be restored by hand. See Managing Workspace Members.

  • An AI assistant can now set a step’s run conditions. Asking one to add a condition — run this step only when the source table has rows, or only when a project variable holds a particular value — reported success and stored nothing, so the step went on running unconditionally with nothing to say a condition had been dropped. Checking the change before writing it reported no problem either, and both creating a step and editing an existing one were affected. Conditions set this way are now stored and evaluated exactly as ones you set on the Conditions tab. The same fix covers a step’s lock, its visibility in the Manager and Explorer views, its retry settings — whether to retry, how many times, and the delay between attempts — and the step it goes to on error.

    The condition list is replaced in full on every write, so an assistant changing one condition has to send every other condition you want to keep; any it leaves out is removed. And a condition that could not be evaluated — one that does not say what it checks, for instance — is now refused rather than stored. Such a condition used to save and then skip the step on every run. A condition that is stored but incomplete, missing the value to compare against or added without Check Conditions Before Running ticked, is reported back as a warning and still written.

    Check Financial Close Workday is the one condition type an assistant cannot set usefully yet. It can write the condition, but that check never matches, so the assistant warns you rather than leaving you to discover it on the next run; set that one on the Conditions tab yourself. Every other condition type is available. See Setting Conditions With an AI Assistant.

  • Changing a workspace member’s email address now updates their reports and dashboards account too. The change saved correctly in PlaidCloud but never carried across, so the member’s account on the reports and dashboards side kept the old address — and nothing reported an error, so the two quietly drifted apart for good. Once they disagreed, anything that looks a person up by email address stopped finding them there, leaving their reports account effectively orphaned under an address they no longer used. An email change now reaches both. If a member’s email address was changed before this fix, the two records are still out of step and need to be reconciled by hand — this release only stops new changes from drifting. See Managing Workspace Members.

  • A read that supplies its own SQL now explains why Row Access declines it. Row Access limits which rows a group may see by filtering the table it is defined against, so a query the caller wrote has no single table to attach that filter to and PlaidCloud declines to run it rather than return rows nothing has vetted. It already declined; the message was written for whoever maintains the row-access code and told a Panel app author to call a function that does not exist in their app. It now names the project, names the ways of reading the same data that do apply the grants — reading a table by name, and the column and dimension value readers — and says a project Architect can run the query as written. An Architect is allowed to, because an Architect can already grant themselves every value of every governed column. The same now covers exporting the results of your own SQL to a file or to another database, and typing a row condition into a fan-out step’s “Test row 1” preview. Nothing changes on a project that has not turned Row Access on. See Row Access and Queries You Write Yourself.

  • Importing an archive into an existing project no longer removes that project’s access restrictions. A project restricted to named users or to security groups was being switched to open access as a side effect of the import, which made it readable — as an Architect — by everyone in the workspace. The restriction was reset because an archive is imported the way a new project is created from one, and a new project is deliberately opened up, since the access lists inside an archive name people from wherever it was exported. That reasoning does not hold for a project that already exists and already has a working access list, so its access type, its lists and its row-access grants are now left exactly as they were. Worth checking: if you have imported an archive into a restricted project, confirm its access setting on the project’s configuration screen. See Importing Into an Existing Project.

  • Importing an archive into an existing project now checks that you can write to that project. The import checked that you were entitled to import something, but never that you had any role on the project you were importing into — so anyone able to import could write an archive’s contents into any project in the workspace, including one they had no access to and one that had been locked to prevent changes. The target project is now checked the way every other change to a project is, and an import into a project you cannot write to, or into a locked project, is refused before anything is read or written. See Importing Into an Existing Project.

  • A project archive no longer includes table data for someone who cannot read the project’s tables. Reading a project’s tables is a separate permission from reading the project itself, and the archive checked it before writing the tables’ definitions but not before writing their rows — so a member holding project access alone could name any table in the project and download its contents inside an archive. Table data is now withheld from anyone without that permission, and the export says which tables were left out.

    Nothing changes for a member who can read the project’s tables. Nor is anything lost: such an archive already carried no table definitions, so restoring one never recreated any tables — the data in it was download-only. The archive is still produced and still carries everything else that member is entitled to, exactly as it already does for workflows, steps, dimensions and every other kind of object they cannot read. Worth checking: if you keep scheduled archives as backups, confirm the member they run as can read the project’s tables, or those archives hold configuration and no data. See Archive a Project.

  • Pre-built queries sent to the platform are now rebuilt under a restriction instead of being trusted. Several Analyze operations — allocate, melt, pivot, update, delete, table exports and view definitions — accept a query that was assembled elsewhere and sent along with the request. The platform used to reconstruct whatever arrived, which meant a crafted request from anything able to reach those operations could have run code inside the server. Such a request now rebuilds only the database-query pieces a genuine query is made of, and anything else is refused with an invalid-argument error. Queries you build in the product are unaffected, and an export that supplies plain SQL rather than a pre-built query works exactly as before.

  • A pre-built query can no longer carry SQL of its own. The change above checks what kind of pieces a pre-built query is rebuilt from, but not the text those pieces hold — so a crafted request could still hand the warehouse a statement of its own choosing, reading a table the query never named. That text is now checked too: a literal SQL fragment must be a single value rather than a statement, and a name that asks to skip quoting must be an ordinary identifier.

    Queries you build in the product are unaffected, as are column names containing spaces, dots or quotation marks — those are quoted for you and always were. Two expression shapes stop working, both in sqlalchemy.literal_column. Text that is a subquery is now refused, because that is the shape that reads a table the query never declared — build it with sqlalchemy.select(...) instead, .scalar_subquery() for a single value or .subquery() for a table to select from, both of which the expression editor already accepts. And text whose outermost operator is OR is refused, because a condition added after it binds to only half of it; put brackets round it, (a OR b), and it works as before. See Reading Another Table From an Expression.

  • The same rule now applies to an expression you write in the product, not only to a pre-built query sent to it. The change above checks a query that arrives already assembled. An expression typed into a data mapper or a step’s filter is built inside the platform and never arrives that way, so it was not checked — and it reaches a query all the same: an allocation step’s source filter is turned into SQL and put directly into the query’s WHERE clause. A sqlalchemy.literal_column there could read a table the step never named, or leave a condition added after it guarding only half the clause.

    Those expressions are now held to exactly the rule described above, so an expression that works in one place works in the other. Inside sqlalchemy.literal_column only: text that is a subquery is refused — build it with sqlalchemy.select(...); text whose outermost operator is OR is refused — put brackets round it; XOR is refused wherever it appears — write it as (a AND NOT b) OR (NOT a AND b); and text carrying a comment is refused, because a comment silently erases whatever the platform adds after it. -- is refused where it would run to the end of the statement; # is refused anywhere at all, including inside a quoted string and including Postgres’ #> and #>> JSON path operators. # opens a comment on MySQL-compatible warehouses such as StarRocks, and which warehouse will run the expression is not known when it is written — so there is no position in the text where it is reliably safe. If you need the character itself, pass it as a value with sqlalchemy.literal('#'). Everything else is unchanged — literal_column('current_date'), a CASE, a cast, a window function, a warehouse-specific function, a bracketed disjunction, and func.count(), which builds one of these for you. When an AI assistant checks an expression for you it now names the shape it refused and what to write instead. See Reading Another Table From an Expression.

  • Editing a security group’s permissions no longer removes the permissions you don’t hold yourself. Anyone who was not a workspace administrator silently stripped every permission on that group they could not grant themselves — just by opening the permission matrix and saving it, even without changing anything. Workspace administrators were unaffected, which is why this looked like permissions disappearing at random for some people and never for others, and why a permission held by only a few, such as Panel app management, would drop off repeatedly and have to be re-added. Those permissions are now left untouched.

    Review any security group that a non-administrator has edited and confirm its permissions are what you expect — a permission removed this way was removed for everyone in the group. See Managing Security Groups and Assignments.

  • A permission you do not hold can no longer be granted through the permission matrix. The form only ever offered the permissions you are allowed to control, but a request naming others was accepted anyway, so someone able to manage users could grant a group — and through it themselves — broader access than they held. Permissions being granted are now checked against your own.

  • Permission and membership changes are recorded in the security log. Changing a group’s permissions or members, or a member’s groups, previously left no record unless the Git server sync failed, so a permission that changed could not be attributed to anyone afterwards. Every change is now logged with what was granted and what was revoked. See Performing a Security Audit.

  • Editing a workflow with the AI assistant can no longer leave it unable to open. Where the assistant changed a workflow’s steps — the reported case was an Import CSV step — a stray, malformed entry could be written into the workflow’s saved structure, and from then on the workflow could not be opened, added to, or have a step removed or switched on or off: every one of those actions failed outright. The places that read a workflow’s structure now step past such an entry instead of failing on it — so a workflow already left in this state opens again with nothing to repair — and the assistant’s save now refuses a malformed entry with a clear error naming it, rather than storing it or dropping it silently, so a bad edit is reported back to the assistant to correct instead of quietly corrupting the workflow.