Skip to content

fix(amazonq): fix for amazon q app initialization failure on sagemaker #7551

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 25, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"type": "Bug Fix",
"description": "Improved Amazon Linux 2 support with better SageMaker environment detection"
}
43 changes: 36 additions & 7 deletions packages/amazonq/src/lsp/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import {
isAmazonLinux2,
getClientId,
extensionVersion,
isSageMaker,
} from 'aws-core-vscode/shared'
import { processUtils } from 'aws-core-vscode/shared'
import { activate } from './chat/activation'
Expand All @@ -53,11 +54,24 @@ import { InlineChatTutorialAnnotation } from '../app/inline/tutorials/inlineChat
const localize = nls.loadMessageBundle()
const logger = getLogger('amazonqLsp.lspClient')

export const glibcLinker: string = process.env.VSCODE_SERVER_CUSTOM_GLIBC_LINKER || ''
export const glibcPath: string = process.env.VSCODE_SERVER_CUSTOM_GLIBC_PATH || ''

export function hasGlibcPatch(): boolean {
return glibcLinker.length > 0 && glibcPath.length > 0
// Skip GLIBC patching for SageMaker environments
if (isSageMaker()) {
getLogger('amazonqLsp').info('SageMaker environment detected in hasGlibcPatch, skipping GLIBC patching')
return false // Return false to ensure SageMaker doesn't try to use GLIBC patching
}

// Check for environment variables (for CDM)
const glibcLinker = process.env.VSCODE_SERVER_CUSTOM_GLIBC_LINKER || ''
const glibcPath = process.env.VSCODE_SERVER_CUSTOM_GLIBC_PATH || ''

if (glibcLinker.length > 0 && glibcPath.length > 0) {
getLogger('amazonqLsp').info('GLIBC patching environment variables detected')
return true
}

// No environment variables, no patching needed
return false
}

export async function startLanguageServer(
Expand All @@ -82,9 +96,24 @@ export async function startLanguageServer(
const traceServerEnabled = Settings.instance.isSet(`${clientId}.trace.server`)
let executable: string[] = []
// apply the GLIBC 2.28 path to node js runtime binary
if (isAmazonLinux2() && hasGlibcPatch()) {
executable = [glibcLinker, '--library-path', glibcPath, resourcePaths.node]
getLogger('amazonqLsp').info(`Patched node runtime with GLIBC to ${executable}`)
if (isSageMaker()) {
// SageMaker doesn't need GLIBC patching
getLogger('amazonqLsp').info('SageMaker environment detected, skipping GLIBC patching')
executable = [resourcePaths.node]
} else if (isAmazonLinux2() && hasGlibcPatch()) {
// Use environment variables if available (for CDM)
if (process.env.VSCODE_SERVER_CUSTOM_GLIBC_LINKER && process.env.VSCODE_SERVER_CUSTOM_GLIBC_PATH) {
executable = [
process.env.VSCODE_SERVER_CUSTOM_GLIBC_LINKER,
'--library-path',
process.env.VSCODE_SERVER_CUSTOM_GLIBC_PATH,
resourcePaths.node,
]
getLogger('amazonqLsp').info(`Patched node runtime with GLIBC using env vars to ${executable}`)
} else {
// No environment variables, use the node executable directly
executable = [resourcePaths.node]
}
} else {
executable = [resourcePaths.node]
}
Expand Down
9 changes: 8 additions & 1 deletion packages/core/src/shared/extensionUtilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { getLogger } from './logger/logger'
import { VSCODE_EXTENSION_ID, extensionAlphaVersion } from './extensions'
import { Ec2MetadataClient } from './clients/ec2MetadataClient'
import { DefaultEc2MetadataClient } from './clients/ec2MetadataClient'
import { extensionVersion, getCodeCatalystDevEnvId } from './vscode/env'
import { extensionVersion, getCodeCatalystDevEnvId, hasSageMakerEnvVars } from './vscode/env'
import globals from './extensionGlobals'
import { once } from './utilities/functionUtils'
import {
Expand Down Expand Up @@ -176,6 +176,13 @@ export function isCloud9(flavor: 'classic' | 'codecatalyst' | 'any' = 'any'): bo
* @returns true if the current system is SageMaker(SMAI or SMUS)
*/
export function isSageMaker(appName: 'SMAI' | 'SMUS' = 'SMAI'): boolean {
// Check for SageMaker-specific environment variables first
if (hasSageMakerEnvVars()) {
getLogger().debug('SageMaker environment detected via environment variables')
return true
}

// Fall back to app name checks
switch (appName) {
case 'SMAI':
return vscode.env.appName === sageMakerAppname
Expand Down
47 changes: 45 additions & 2 deletions packages/core/src/shared/vscode/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,13 +125,56 @@ export function isRemoteWorkspace(): boolean {
}

/**
* There is Amazon Linux 2.
* Checks if the current environment has SageMaker-specific environment variables
* @returns true if SageMaker environment variables are detected
*/
export function hasSageMakerEnvVars(): boolean {
// Check both old and new environment variable names
// SageMaker is renaming their environment variables in their Docker images
return (
// Original environment variables
process.env.SAGEMAKER_APP_TYPE !== undefined ||
process.env.SAGEMAKER_INTERNAL_IMAGE_URI !== undefined ||
process.env.STUDIO_LOGGING_DIR?.includes('/var/log/studio') === true ||
// New environment variables (update these with the actual new names)
process.env.SM_APP_TYPE !== undefined ||
process.env.SM_INTERNAL_IMAGE_URI !== undefined ||
process.env.SERVICE_NAME === 'SageMakerUnifiedStudio'
)
}

/**
* Checks if the current environment is running on Amazon Linux 2.
*
* Use {@link isCloudDesktop()} to know if we are specifically using internal Amazon Linux 2.
* This function attempts to detect if we're running in a container on an AL2 host
* by checking both the OS release and container-specific indicators.
*
* Example: `5.10.220-188.869.amzn2int.x86_64` or `5.10.236-227.928.amzn2.x86_64` (Cloud Dev Machine)
*/
export function isAmazonLinux2() {
// First check if we're in a SageMaker environment, which should not be treated as AL2
// even if the underlying host is AL2
if (hasSageMakerEnvVars()) {
return false
}

// Check if we're in a container environment that's not AL2
if (process.env.container === 'docker' || process.env.DOCKER_HOST || process.env.DOCKER_BUILDKIT) {
// Additional check for container OS - if we can determine it's not AL2
try {
const fs = require('fs')
if (fs.existsSync('/etc/os-release')) {
const osRelease = fs.readFileSync('/etc/os-release', 'utf8')
if (!osRelease.includes('Amazon Linux 2') && !osRelease.includes('amzn2')) {
return false
}
}
} catch (e) {
// If we can't read the file, fall back to the os.release() check
}
}

// Standard check for AL2 in the OS release string
return (os.release().includes('.amzn2int.') || os.release().includes('.amzn2.')) && process.platform === 'linux'
}

Expand Down
Loading