Skip to content

fix(secret-sync): handle Railway services with no deployments during sync#6873

Open
devin-ai-integration[bot] wants to merge 1 commit into
mainfrom
devin/1781556369-fix-railway-sync-cron-service
Open

fix(secret-sync): handle Railway services with no deployments during sync#6873
devin-ai-integration[bot] wants to merge 1 commit into
mainfrom
devin/1781556369-fix-railway-sync-cron-service

Conversation

@devin-ai-integration

Copy link
Copy Markdown
Contributor

Context

Railway secret sync crashes with "Failed to sync secrets to Railway" when the target service has no deployments (e.g. cron services).

Root cause: In syncSecrets, after upserting variables, the code fetches the latest deployment and accesses edges[0].node.id without checking if edges is empty. When a service (such as a Railway cron job) has no deployments, edges[0] is undefined and .node.id throws a TypeError, which gets caught by the generic handler and surfaced as a failed sync — even though the variables were written successfully.

Fix:

  • Added optional chaining on edges[0]?.node.id
  • If no deployment exists, skip the redeploy step instead of throwing
- const latestDeploymentId = latestDeployment?.deployments.edges[0].node.id;
- if (!latestDeploymentId)
-   throw new SecretSyncError({
-     message: "Failed to get latest deployment from Railway"
-   });
+ const latestDeploymentId = latestDeployment?.deployments.edges[0]?.node.id;
+ // Some Railway services (e.g. cron jobs) may not have deployments to redeploy
+ if (!latestDeploymentId) return;

Steps to verify the change

  1. Set up a Railway secret sync targeting a cron service (a service with no deployments)
  2. Trigger a sync — should succeed without error
  3. Verify variables are written to the Railway service

Type

  • Fix
  • Feature
  • Improvement
  • Breaking
  • Docs
  • Chore

Checklist

  • Title follows the conventional commit format: type(scope): short description (scope is optional, e.g., fix: prevent crash on sync or fix(api): handle null response).
  • Tested locally
  • Updated docs (if needed)
  • Updated CLAUDE.md files (if needed)
  • Read the contributing guide

Link to Devin session: https://app.devin.ai/sessions/47389380e59b4e2baa484bd70ebebd7a
Requested by: @ashwin-infisical

…sync

Safely access the first deployment edge with optional chaining and
skip the redeploy step when no deployments exist (e.g. cron services)
instead of crashing with a TypeError.

Co-Authored-By: ashwin <ashwin@infisical.com>
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@greptile-apps

greptile-apps Bot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a crash in the Railway secret sync when targeting a service with no deployments (e.g. cron jobs). The variables are still written successfully to Railway; the only skipped step is the post-write redeploy trigger.

  • Adds optional chaining (edges[0]?.node.id) to avoid a TypeError when the deployments list is empty.
  • Replaces the throw new SecretSyncError on a missing deployment ID with a graceful return, treating services without deployments as a normal, non-error case.

Confidence Score: 4/5

The change is safe to merge; it fixes a real crash for services with no deployments and secrets are still written correctly.

The fix correctly handles the empty-deployments case and the variables write path is unaffected. The only non-blocking concern is that the return silently succeeds for any falsy deployment ID, not just the expected no-deployments scenario, which could obscure unexpected API response shapes in the future.

backend/src/services/secret-sync/railway/railway-sync-fns.ts — the early-return logic around line 100

Important Files Changed

Filename Overview
backend/src/services/secret-sync/railway/railway-sync-fns.ts Added optional chaining on edges[0]?.node.id and changed the missing-deployment path from a thrown error to a graceful return, allowing services without deployments (e.g. cron jobs) to sync secrets successfully.

Reviews (1): Last reviewed commit: "fix(secret-sync): handle Railway service..." | Re-trigger Greptile

Comment on lines +97 to +100
const latestDeploymentId = latestDeployment?.deployments.edges[0]?.node.id;

if (!latestDeploymentId)
throw new SecretSyncError({
message: "Failed to get latest deployment from Railway"
});
// Some Railway services (e.g. cron jobs) may not have deployments to redeploy
if (!latestDeploymentId) return;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Silent return also swallows unexpected API response shapes

The return on line 100 now fires for any falsy latestDeploymentId, not only when no deployments exist. If getDeployments returns a result where deployments is present but edges[0] has a falsy/empty id (e.g. an unexpected API shape change), the sync will report success while silently skipping the redeploy. The original guard at least surfaced that case as an observable failure. Consider logging a warning before returning so operators can distinguish "service has no deployments (expected)" from "service has deployments but the id was unexpectedly empty (unexpected)".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant