You’re very close — the error you’re seeing (CredentialsProviderError: Could not load credentials from any providers) isn’t really about your endpoint, but rather about AWS SDK v3 trying to sign the request even though it’s hitting your local serverless-offline WebSocket server.
Let’s walk through what’s happening and how to fix it.
When you do:
const apiGatewayClient = new ApiGatewayManagementApiClient({ endpoint });
await apiGatewayClient.send(new PostToConnectionCommand(payload));
The AWS SDK v3 automatically assumes it’s talking to real AWS API Gateway, so it:
Attempts to sign the request with AWS credentials.
Fails because serverless-offline doesn’t need or support signed requests.
Hence: Could not load credentials from any providers.
So even though your endpoint (http://localhost:3001) is correct, the client is still trying to sign requests as if it were AWS.
When using serverless-offline for WebSocket testing, you need to give the ApiGatewayManagementApiClient dummy credentials and a local region.
Here’s a working local setup:
const {
ApiGatewayManagementApiClient,
PostToConnectionCommand,
} = require("@aws-sdk/client-apigatewaymanagementapi");
exports.message = async (event, context) => {
// Use the same port that serverless-offline shows for websocket
const endpoint = "http://localhost:3001";
const connectionId = event.requestContext.connectionId;
const payload = {
ConnectionId: connectionId,
Data: "pong",
};
const apiGatewayClient = new ApiGatewayManagementApiClient({
endpoint,
region: "us-east-1",
// Dummy credentials to satisfy SDK signer
credentials: {
accessKeyId: "dummy",
secretAccessKey: "dummy",
},
});
try {
await apiGatewayClient.send(new PostToConnectionCommand(payload));
} catch (err) {
console.error("PostToConnection error:", err);
}
return { statusCode: 200, body: "pong sent" };
};
The AWS SDK v3 doesn’t let you completely disable signing, but it’s happy if you provide any credentials.
Since serverless-offline ignores them, “dummy” values are perfectly fine locally.
Start serverless offline:
npx serverless offline
Connect via WebSocket client (e.g., wscat):
npx wscat -c ws://localhost:3001
Type a message — you should see "pong" echoed back.
ProblemFixSDK tries to sign local requestsProvide dummy credentialsWrong endpointUse http://localhost:3001 (as printed by serverless-offline)Missing regionAdd region: "us-east-1"
If you want, I can also show you how to make this conditional (so it automatically switches between local and AWS endpoints depending on IS_OFFLINE), which makes deployments smoother. Would you like that?