{"record":{"id":"94a497cb7605ab68","repo":"eyaltoledano/claude-task-master","slug":"missing-configuration-94a497","errorCode":"MISSING_CONFIGURATION","errorMessage":"API storage not fully configured (${missing.join(', ') || 'credentials missing'}). Run: tm auth login, or set the missing field(s).","messagePattern":"API storage not fully configured \\((.+?)\\)\\. Run: tm auth login, or set the missing field\\(s\\)\\.","errorType":"exception","errorClass":"TaskMasterError","httpStatus":null,"severity":"error","filePath":"packages/tm-core/src/modules/storage/services/storage-factory.ts","lineNumber":73,"sourceCode":"\n\t\tconst logger = getLogger('StorageFactory');\n\n\t\tswitch (storageType) {\n\t\t\tcase 'file':\n\t\t\t\tlogger.debug('📁 Using local file storage');\n\t\t\t\treturn StorageFactory.createFileStorage(projectPath, config);\n\n\t\t\tcase 'api':\n\t\t\t\tif (!StorageFactory.isHamsterAvailable(config)) {\n\t\t\t\t\tconst missing: string[] = [];\n\t\t\t\t\tif (!config.storage?.apiEndpoint) missing.push('apiEndpoint');\n\t\t\t\t\tif (!config.storage?.apiAccessToken) missing.push('apiAccessToken');\n\n\t\t\t\t\t// Check if authenticated via AuthManager\n\t\t\t\t\tconst authManager = AuthManager.getInstance();\n\t\t\t\t\tconst hasSession = await authManager.hasValidSession();\n\t\t\t\t\tif (!hasSession) {\n\t\t\t\t\t\tthrow new TaskMasterError(\n\t\t\t\t\t\t\t`API storage not fully configured (${missing.join(', ') || 'credentials missing'}). Run: tm auth login, or set the missing field(s).`,\n\t\t\t\t\t\t\tERROR_CODES.MISSING_CONFIGURATION,\n\t\t\t\t\t\t\t{ storageType: 'api', missing }\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\t// Use auth token from AuthManager\n\t\t\t\t\tconst accessToken = await authManager.getAccessToken();\n\t\t\t\t\tif (accessToken) {\n\t\t\t\t\t\t// Merge with existing storage config, ensuring required fields\n\t\t\t\t\t\tconst nextStorage: StorageSettings = {\n\t\t\t\t\t\t\t...(config.storage as StorageSettings),\n\t\t\t\t\t\t\ttype: 'api',\n\t\t\t\t\t\t\tapiAccessToken: accessToken,\n\t\t\t\t\t\t\tapiEndpoint:\n\t\t\t\t\t\t\t\tconfig.storage?.apiEndpoint ||\n\t\t\t\t\t\t\t\tprocess.env.TM_BASE_DOMAIN ||\n\t\t\t\t\t\t\t\tprocess.env.TM_PUBLIC_BASE_DOMAIN ||\n\t\t\t\t\t\t\t\t'https://tryhamster.com/api'","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/eyaltoledano/claude-task-master/blob/c0c98d367c55296bfe69e65680625b6db437af02/packages/tm-core/src/modules/storage/services/storage-factory.ts#L55-L91","documentation":"StorageFactory.create throws a TaskMasterError with code MISSING_CONFIGURATION when storage type 'api' is requested but no API access token is configured and AuthManager has no valid session. API-backed storage cannot authenticate without either an explicit apiAccessToken or a logged-in session.","triggerScenarios":"Creating API storage via createFromStorageConfig when config.storage.apiAccessToken is unset AND AuthManager.hasValidSession() returns false — i.e. never ran `tm auth login` and no token in config/env.","commonSituations":"Fresh machine or CI environment without `tm auth login`; expired/invalidated session; misconfigured storage type set to 'api' when intending file storage; token field name typo in config.","solutions":["Run `tm auth login` to establish a valid session before creating API storage","Set storage.apiAccessToken in the storage config to a valid token","Fix the storage type in config if file storage was intended","Verify the token/env var is present in CI (secret not injected)"],"exampleFix":"// before\nconst storage = await StorageFactory.createFromStorageConfig({ storageType: 'api' });\n// after\nconst authManager = AuthManager.getInstance();\nif (!await authManager.hasValidSession()) {\n  throw new Error('Run: tm auth login before using API storage');\n}\nconst storage = await StorageFactory.createFromStorageConfig({ storageType: 'api' });","handlingStrategy":"validation","validationCode":"const authManager = AuthManager.getInstance();\nconst hasSession = await authManager.hasValidSession();\nconst hasToken = Boolean(config.storage?.apiAccessToken);\nif (!hasSession && !hasToken) {\n  throw new Error('API storage requires `tm auth login` or storage.apiAccessToken');\n}\nconst storage = await StorageFactory.createFromStorageConfig(config);","typeGuard":null,"tryCatchPattern":"try {\n  const storage = await StorageFactory.createFromStorageConfig(config);\n} catch (e) {\n  if (e instanceof TaskMasterError && e.code === ERROR_CODES.MISSING_CONFIGURATION) {\n    console.error('API storage not configured:', e.details?.missing);\n    console.error('Fix: run `tm auth login` or set storage.apiAccessToken');\n  }\n  throw e;\n}","preventionTips":["Run `tm auth login` during environment/CI setup","Prefer file storage unless API storage is explicitly required","Inject apiAccessToken via CI secrets, not committed config","Check session validity with AuthManager before constructing storage"],"tags":["authentication","configuration","api","missing-token"],"backgroundTag":"missing-api-credentials","analyzedSha":"c0c98d367c55296bfe69e65680625b6db437af02","analyzedAt":"2026-08-29T02:56:26.071Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}