Skip to content

Troubleshooting Synectic Runtime Errors

Nicholas Nelson edited this page Sep 9, 2020 · 1 revision

TypeScript catches most compile-time errors, but can only statically reason about errors in Synectic during run-time. Therefore, some errors cannot be observed without compiling and executing Synectic.

For example, the following Uncaught SyntaxError: Unexpected token '!' is thrown on run-time even though no type checker errors are given: unexpected_token_error

The actual location of the fault requires an understanding of how Synectic is built and packaged. Using Electron and Electron Forge, we bundle the compiled code for Synectic into a single index.js file that contains all compiled code not part of a third-party package. This is why the location of the error is shown as index.js:167202, which corresponds to the updateBranches() method from the src/containers/repos.ts file within the Synectic source code: index_js_fault_location

And the root cause arises because the updateBranches() method contains a type signature of ThunkAction<Promise<NarrowActionType<ActionKeys.UPDATE_REPO> | undefined>, RootState, undefined, Action>, which means that the asynchronous ThunkAction should be dispatching either a UpdateRepoAction (denoted by the NarrowActionType<ActionKeys.UPDATE_REPO> which type narrows the exported Redux Action) or undefined against the Redux store. Both of these are valid dispatches to the Redux store, but we also check for the existence of repo and throw an Error if it doesn't exist in the Redux store. This Error short-circuits the logic within the method and prematurely exits the control flow path, thus causing the cryptic Uncaught SyntaxError: Unexpected token '!'.

/**
 * Thunk Action Creator for examining and updating the list of Git branch refs associated with a Repository
 * in the Redux store. Any local or remote branches are captured and added to the associated fields in the
 *  Repository, and the Redux store is updated to reflect these changes.
 * @param root The root Git directory path associated with the `Repository` object.
 * @param repo The `Repository` object that needs to be updated with the latest branch `refs` list.
 * @return A Thunk that can be executed to simultaneously dispatch Redux updates and return the updated `Repository` object 
 * from the Redux store.
 */
export const updateBranches = (id: UUID): ThunkAction<Promise<NarrowActionType<ActionKeys.UPDATE_REPO> | undefined>, RootState, undefined, Action> =>
  async (dispatch, getState) => {
    const repo = getState().repos[id];
    if (!repo) throw new Error('Redux Error: Cannot update a repository that does not exist in the store.');
    const localBranches = await isogit.listBranches({ fs: fs, dir: repo.root.toString() });
    const remoteBranches = await isogit.listBranches({ fs: fs, dir: repo.root.toString(), remote: 'origin' });
    return dispatch(updateRepository({ ...repo, local: localBranches, remote: remoteBranches }));
  };