github-community-projects / github-community-projects/safe-settings
full-sync crashes on 2.1.19+ with "Cannot read properties of null (reading 'info')" — probot 14 leaves Probot#log null
- Dominant language
- JavaScript
- Stars
- 921
- Forks
- 226
- Avg merge
- 18h 3m
- Merged PRs (30d)
- 14
Description
## Problem Description
### What is actually happening
`npm run full-sync` (Actions mode) crashes immediately on 2.1.19, 2.1.20 and
2.1.21. It fails before any GitHub API call, so a scheduled full sync never
starts and nothing is reconciled.
`full-sync.js` calls `probot.log.info()` as the first statement after
`createProbot()`:
```js
const probot = createProbot()
probot.log.info(`Starting full sync with NOP=${nop}`) // line 7
```
Since 2.1.19 the `probot` dependency is `^14.2.4`. In probot 14,
[`src/probot.ts`](https://github.com/probot/probot/blob/v14.2.4/src/probot.ts)
declares the logger nullable and initialises it to `null`:
```ts
log: Logger | null; // line 55
...
log: options.log || null, // line 114
```
The real logger is only constructed later, during initialization
(lines ~153–163), and probot's own code guards the field accordingly:
```ts
if (this.#state.log) { // line 203
```
`createProbot()` returns before any of that runs, so `probot.log` is `null`
and the dereference on `full-sync.js:7` throws.
This is not configuration-dependent: no environment variable affects it.
`LOG_LEVEL` is irrelevant because the logger object does not exist yet.
### What is the expected behavior
`full-sync` starts and reconciles, as it does on 2.1.18.
### Error output, if available
```
> safe-settings@0.1.0-rc.26 full-sync
> node ./full-sync.js
Fatal error during full sync: TypeError: Cannot read properties of null (reading 'info')
at performFullSync (/home/runner/work/.github/.github/.safe-settings/full-sync.js:7:14)
at Object. (/home/runner/work/.github/.github/.safe-settings/full-sync.js:25:1)
at Module._compile (node:internal/modules/cjs/loader:1781:14)
at Object..js (node:internal/modules/cjs/loader:1913:10)
at Module.load (node:internal/modules/cjs/loader:1505:32)
at Function._load (node:internal/modules/cjs/loader:1309:12)
at wrapModuleLoad (node:internal/modules/cjs/loader:254:19)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:171:5)
```
### Affected versions
| tag | `probot` | `engines.node` | full-sync |
|---|---|---|---|
| 2.1.18 | `^13.4.4` | `>= 16.0.0` | works |
| 2.1.19 | `^14.2.4` | `>= 22.0.0` | crashes |
| 2.1.20 | `^14.2.4` | `>= 22.0.0` | crashes |
| 2.1.21 | `^14.2.4` | `>= 22.0.0` | crashes |
`full-sync.js` is byte-identical between 2.1.18 and 2.1.21, so the change in
behaviour comes entirely from the probot major bump, not from an edit to that
file.
`3.0.0-rc.1` still pins `probot: ^13.4.4`, so it is unaffected — but its
`full-sync.js` has the same unguarded `probot.log.info()` on the line after
`createProbot()`, so the same crash returns if that branch ever moves to
probot 14. `2.2.0-rc.2` has the same shape at the top level of the module.
### Reproduction
Any Actions-mode setup on 2.1.19+ reproduces it; the config is irrelevant
because it crashes before reading anything:
```yaml
- uses: actions/checkout@v5
with: { repository: github-community-projects/safe-settings, ref: 2.1.21, path: .safe-settings }
- run: npm ci
working-directory: .safe-settings
- run: npm run full-sync
working-directory: .safe-settings
env:
GH_ORG:
APP_ID: ${{ vars.SAFE_SETTINGS_APP_ID }}
PRIVATE_KEY: ${{ secrets.SAFE_SETTINGS_PRIVATE_KEY }}
ADMIN_REPO: .github
CONFIG_PATH: safe-settings
```
### Possible fixes
I have not sent a PR because the right choice depends on how you want probot
14 supported, but the options seem to be:
1. Obtain a logger explicitly rather than relying on the instance field, e.g.
pass one in via `createProbot({ overrides: { log } })`.
2. Await whatever initialises the instance before the first `log` use.
3. Guard the call sites in `full-sync.js` — this keeps it running but silently
loses the "Starting full sync" and "Full sync completed successfully" lines,
which are the only account of a run in Actions mode.
4. Pin `probot` back to `^13` until 14 is supported deliberately.
Whichever is chosen, `full-sync.js` uses `probot.log` in three places — the
two `info` calls and the `error` call in the `settings.errors` branch — so all
of them need the same treatment.
## Context
### Are you using the hosted instance of probot/settings or running your own?
Running our own, in Actions mode (`npm run full-sync` from a workflow), not a
hosted Probot service.
### If running your own instance, are you using it with github.com or GitHub Enterprise?
github.com.
#### Version of probot/settings
2.1.21 (also confirmed on 2.1.19 and 2.1.20 by inspection; 2.1.18 works).
#### Version of GitHub Enterprise
N/A.
Contributor guide
Research direction
Start with full-sync.js, createProbot(), and the three probot.log call sites, then run npm run full-sync in the documented Actions-mode setup. Compare the logger lifecycle described for probot 14 and determine a consistent treatment for all calls. Done means full-sync starts and reconciles on 2.1.19+ without losing its run-status logging.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, node.js
- Domain
- cli, devops
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 58/100