{"record":{"id":"9ceabe5a0107eea5","repo":"paperclipai/paperclip","slug":"railway-ssh-setup-required","errorCode":"railway_ssh_setup_required","errorMessage":"Configure Container access on this Railway connection before running commands.","messagePattern":"Configure Container access on this Railway connection before running commands\\.","errorType":"error_code","errorClass":"RailwayError","httpStatus":422,"severity":"error","filePath":"server/src/services/railway.ts","lineNumber":304,"sourceCode":"          case \"redeploy\":\n            if (!deployment?.canRedeploy) throw new RailwayError(\"railway_deployment_ineligible\", \"Railway does not allow this deployment to be redeployed.\", 409);\n            result = await query(RAILWAY_QUERIES.redeploy, { deploymentId: args.deploymentId });\n            if (!id.safeParse(record(record(result).deploymentRedeploy).id).success) throw new RailwayError(\"railway_operation_unconfirmed\", \"Railway did not confirm a resulting deployment. Inspect deployment status before retrying.\");\n            break;\n          case \"restart\":\n            result = await query(RAILWAY_QUERIES.restart, { deploymentId: args.deploymentId });\n            if (record(result).deploymentRestart !== true) throw new RailwayError(\"railway_operation_unconfirmed\", \"Railway did not confirm the restart. Inspect deployment status before retrying.\");\n            result = { ...record(result), targetDeploymentId: args.deploymentId };\n            break;\n          case \"rollback\":\n            if (!deployment?.canRollback) throw new RailwayError(\"railway_deployment_ineligible\", \"Railway does not allow rollback to this deployment.\", 409);\n            result = await query(RAILWAY_QUERIES.rollback, { deploymentId: args.deploymentId });\n            if (record(result).deploymentRollback !== true) throw new RailwayError(\"railway_operation_unconfirmed\", \"Railway did not confirm the rollback. Inspect deployment status before retrying.\");\n            result = { ...record(result), targetDeploymentId: args.deploymentId };\n            break;\n          case \"run-command\":\n            if (!Array.isArray(deployment?.instances) || !deployment.instances.some((entry: { id: string }) => entry.id === args.deploymentInstanceId) || deployment.status !== \"SUCCESS\") throw new RailwayError(\"railway_target_mismatch\", \"The container instance is not part of the selected running deployment.\", 403);\n            if (!options.runCommand) throw new RailwayError(\"railway_ssh_setup_required\", \"Configure Container access on this Railway connection before running commands.\", 422);\n            result = await options.runCommand({ deploymentInstanceId: args.deploymentInstanceId, command: args.command, timeoutSeconds: args.timeoutSeconds, signal: options.signal }); break;\n        }\n      }\n      return redact(result ?? null);\n    },\n  };\n}\n","sourceCodeStart":286,"sourceCodeEnd":312,"githubUrl":"https://github.com/paperclipai/paperclip/blob/3f1d897a7c018d76563a21c6e39c3c9b03933622/server/src/services/railway.ts#L286-L312","documentation":"RailwayError with code railway_ssh_setup_required (HTTP 422) thrown when the run-command operation passes the target check but the Railway connection was created without a runCommand capability. Executing commands inside a Railway container requires Container access (SSH/exec) configured on the connection credentials; without it the tool cannot perform the operation and refuses with 422 instead of failing at exec time.","triggerScenarios":"Calling the railway run-command tool on a connection whose options.runCommand is undefined — i.e. the connection was configured without Container access/SSH credentials, or the connection factory did not wire the runCommand executor.","commonSituations":"Fresh Railway integration where only the API token was configured; connection created before Container-access feature was enabled; credentials expired or were rotated and the exec capability was dropped during reconnect; run-command used on a read-only connection.","solutions":["Open the Railway connection settings and enable/configure Container access (SSH/exec credentials), then reconnect the tool","Verify the connection factory that builds options actually passes a runCommand executor for this connection type","Re-authorize the Railway connection if Container-access credentials were revoked or rotated","As a workaround, use redeploy/restart/rollback or read-logs, which do not require Container access"],"exampleFix":"// before (connection options)\nconst options = { token, redact }; // no runCommand\n// after\nconst options = { token, redact, runCommand: createRailwayRunCommand({ sshCredentials }), signal };\nawait railway.call('railway_run-command', { deploymentId, deploymentInstanceId, command: 'ls' });","handlingStrategy":"validation","validationCode":"if (typeof railwayOptions.runCommand !== 'function') {\n  throw new Error('Railway connection lacks Container access; configure SSH/exec credentials before run-command');\n}","typeGuard":"function hasContainerAccess(options) {\n  return typeof options === 'object' && options !== null && typeof options.runCommand === 'function';\n}","tryCatchPattern":"try {\n  result = await railway.call('railway_run-command', { deploymentId, deploymentInstanceId, command });\n} catch (e) {\n  if (e?.code === 'railway_ssh_setup_required') {\n    // surface setup instructions to the operator or fall back to redeploy/read-logs\n  } else throw e;\n}","preventionTips":["Configure Container access when creating the Railway connection, not at first use","After credential rotation, re-create the connection so runCommand is rewired","Feature-check options.runCommand before offering run-command to agents","Fall back to non-exec operations (restart, read-logs) when exec is unavailable"],"tags":["railway","configuration","ssh","container-access"],"backgroundTag":"missing-required-config","analyzedSha":"3f1d897a7c018d76563a21c6e39c3c9b03933622","analyzedAt":"2026-09-18T08:03:59.046Z","contentChangedAt":"2026-09-18T08:03:59.046Z","schemaVersion":2},"datasetVersion":"2026-09-22T11:17:16.035Z"}